Go back to Richel Bilderbeek's homepage.

Go back to Richel Bilderbeek's C++ page.

 

 

 

 

 

(C++) TestQtOcrWidget

 

TestQtOcrWidget is a tool to test the QtOcrWidget class.

 

 

 

 

 

Downloads

 

Technical facts

 

Operating system(s) or programming environment(s)

IDE(s):

Project type:

C++ standard:

Compiler(s):

Libraries used:

 

 

 

 

 

Qt project file: ./ToolTestQtOcrWidget/ToolTestQtOcrWidgetDesktop.pro

 

include(../../DesktopApplicationNoWeffcpp.pri)

include(../../Libraries/GeneralConsole.pri)
include(../../Libraries/GeneralDesktop.pri)
include(../../Libraries/Boost.pri)
include(../../Libraries/Tesseract.pri) #Cannot use -Weffc++

include(../../Tools/ToolTestQtOcrWidget/ToolTestOcrWidgetDesktop.pri)

SOURCES += \
    qtmain.cpp

 

 

 

 

 

./ToolTestQtOcrWidget/ToolTestOcrWidgetDesktop.pri

 

include(../../Tools/ToolTestQtOcrWidget/ToolTestQtOcrWidgetConsole.pri)

SOURCES += \
    ../../Tools/ToolTestQtOcrWidget/qtocrinputdialog.cpp \
    ../../Tools/ToolTestQtOcrWidget/qtocrwidget.cpp \
    ../../Tools/ToolTestQtOcrWidget/qtsketchwidget.cpp

HEADERS  += \
    ../../Tools/ToolTestQtOcrWidget/qtocrinputdialog.h \
    ../../Tools/ToolTestQtOcrWidget/qtocrwidget.h \
    ../../Tools/ToolTestQtOcrWidget/qtsketchwidget.h

FORMS += \
    ../../Tools/ToolTestQtOcrWidget/qtocrinputdialog.ui

 

 

 

 

 

./ToolTestQtOcrWidget/ToolTestQtOcrWidgetConsole.pri

 

INCLUDEPATH += \
    ../../Tools/ToolTestQtOcrWidget

SOURCES += \
    ../../Tools/ToolTestQtOcrWidget/ocr.cpp \
    ../../Tools/ToolTestQtOcrWidget/tesseracthelper.cpp


HEADERS  += \
    ../../Tools/ToolTestQtOcrWidget/ocr.h \
    ../../Tools/ToolTestQtOcrWidget/tesseracthelper.h

RESOURCES += \
    ../../Tools/ToolTestQtOcrWidget/ToolTestQtOcrWidget.qrc

OTHER_FILES += \
    ../../Tools/ToolTestQtOcrWidget/eng.traineddata

 

 

 

 

 

./ToolTestQtOcrWidget/ocr.h

 

#ifndef OCR_H
#define OCR_H

#include <string>
//#include <utility>
//#include <vector>

#include <boost/shared_ptr.hpp>

namespace tesseract { struct TessBaseAPI; }

///OCR is an adapter for Tesseract
struct Ocr
{
  Ocr(const std::string& data_path,
  const std::string& whitelist);
  const std::string Read(
    const unsigned char * const image_data,
    const int bytes_per_pixel,
    const int bytes_per_line,
    const int left,
    const int top,
    const int width,
    const int height) const;

  private:
  const boost::shared_ptr<tesseract::TessBaseAPI> m_api;
};

#endif // OCR_H

 

 

 

 

 

./ToolTestQtOcrWidget/ocr.cpp

 

#pragma GCC diagnostic push
#pragma GCC diagnostic ignored "-Weffc++"
#include "ocr.h"

#include <cassert>
#include <cstdlib>
#include <fstream>
#include <iostream>

#include <QFile>

#include "tesseract-3.00/api/baseapi.h"
#pragma GCC diagnostic pop

Ocr::Ocr(
  const std::string& datafile,
  const std::string& whitelist)
  : m_api(new tesseract::TessBaseAPI)
{
  //assert(QFile::exists(datafile.c_str())); //Tesseract adds path

  const int success = m_api->Init(datafile.c_str(),"eng"); //English
  assert(success == 0);

  //CCUtil::main_setup(

  //tesseract::TessdataManager::Init(datafile.c_str());
  m_api->SetVariable("tessedit_char_whitelist", whitelist.c_str());
  //m_api->SetVariable("tessedit_char_whitelist", "ABCDEFGHIJKLMNOPQRSTUVWXYZ");
}

const std::string Ocr::Read(
  const unsigned char * const image_data,
  const int bytes_per_pixel,
  const int bytes_per_line,
  const int left,
  const int top,
  const int width,
  const int height) const
{
  assert(width  > 0);
  assert(height > 0);

  const std::string text
    = m_api->TesseractRect(
    image_data,
    bytes_per_pixel,
    bytes_per_line,
    left,
    top,
    width,
    height);
  return text;
}

 

 

 

 

 

./ToolTestQtOcrWidget/qtmain.cpp

 

#pragma GCC diagnostic push
#pragma GCC diagnostic ignored "-Weffc++"
#include <algorithm>
#include <cassert>
#include <string>

#include <QApplication>
#include <QDir>
#include <QFile>

#include "ocr.h"
#include "qtocrinputdialog.h"
#include "qtocrwidget.h"
#pragma GCC diagnostic pop

int main(int argc, char *argv[])
{
  QApplication a(argc, argv);

  //Check if dataset exists. If not, recreate it
  const std::string qrcfilename = "eng.traineddata";
  //Tesseract wants it to be in a folder called tessdata
  const std::string tesseract_filename = "tessdata/eng.traineddata";
  if (!QFile::exists(tesseract_filename.c_str()))
  {
    QFile f( (std::string(":/data/") + qrcfilename).c_str() );
    assert(f.size() > 0);
    QDir().mkdir("tessdata");
    bool success = f.copy(tesseract_filename.c_str());

    assert(success);
    f.close();
  }
  assert(QFile::exists(tesseract_filename.c_str()));

  //The chars enabled to be detected
  const std::string whitelist = "ABCDEFGHIJKLMNOPQRSTUVWXYZ";
  //But Tesseract wants the qrc filename, because it will add the 'tessdata' folder itself
  QtOcrInputDialog w(std::string("./") + qrcfilename,whitelist);

  w.show();

  return a.exec();
}

 

 

 

 

 

./ToolTestQtOcrWidget/qtocrinputdialog.h

 

#ifndef QTOCRDIALOG_H
#define QTOCRDIALOG_H

#include <boost/shared_ptr.hpp>

#include <QDialog>

namespace Ui {
  class QtOcrInputDialog;
}

struct QtOcrWidget;

///QtOcrInputDialog displays a GUI for the QtOcrWidget
class QtOcrInputDialog : public QDialog
{
  Q_OBJECT

public:
  explicit QtOcrInputDialog(
    const std::string& path,
    const std::string& whitelist,
    QWidget *parent = 0);
  ~QtOcrInputDialog();

protected:
  void paintEvent(QPaintEvent *);

private slots:
  void on_button_clear_clicked();

private:
  Ui::QtOcrInputDialog *ui;
  boost::shared_ptr<QtOcrWidget> m_ocr_widget;
};

#endif // QTOCRDIALOG_H

 

 

 

 

 

./ToolTestQtOcrWidget/qtocrinputdialog.cpp

 

#pragma GCC diagnostic push
#pragma GCC diagnostic ignored "-Weffc++"
#include "qtocrinputdialog.h"

#include <algorithm>
#include <numeric>
#include <string>

#include <QDesktopWidget>
#include <QPainter>

#include <cassert>

#include "qtocrwidget.h"
#include "ui_qtocrinputdialog.h"
#pragma GCC diagnostic pop

QtOcrInputDialog::QtOcrInputDialog(
  const std::string& path,
  const std::string& whitelist,
  QWidget *parent)
  : QDialog(parent),
    ui(new Ui::QtOcrInputDialog),
    m_ocr_widget(new QtOcrWidget(path,whitelist))
{
  ui->setupUi(this);

  {
    assert(!ui->ocr_widget_placeholder->layout());
    QLayout * const layout = new QGridLayout;
    ui->ocr_widget_placeholder->setLayout(layout);
    layout->addWidget(m_ocr_widget.get());
    assert(ui->ocr_widget_placeholder->layout());
  }

  m_ocr_widget->resize(m_ocr_widget->size());
}

QtOcrInputDialog::~QtOcrInputDialog()
{
  delete ui;
}

void QtOcrInputDialog::paintEvent(QPaintEvent *)
{
  assert(m_ocr_widget);

  std::string s = m_ocr_widget->Read();

  ///Remove trailing '\n' and '\r'
  while (1)
  {
    if (s.empty()) break;
    const char last_char = s.substr(s.size()-1,1)[0];
    if (last_char == '\r' || last_char == '\n')
    {
      s.resize(s.size() - 1);
    }
    else
    {
      break;
    }
  }
  this->setWindowTitle(s.c_str());
}

void QtOcrInputDialog::on_button_clear_clicked()
{
  m_ocr_widget->clear();
}

 

 

 

 

 

./ToolTestQtOcrWidget/qtocrwidget.h

 

#ifndef QTOCRWIDGET_H
#define QTOCRWIDGET_H

#include <vector>

#include <boost/shared_ptr.hpp>

#include "qtsketchwidget.h"

struct Ocr;

class QtOcrWidget : public QtSketchWidget
{
  Q_OBJECT
public:
  explicit QtOcrWidget(
    const std::string& path,
    const std::string& whitelist,
    QWidget *parent = 0);

  const std::string Read() const;

protected:

private:
  boost::shared_ptr<Ocr> m_ocr;
};

#endif // QTOCRWIDGET_H

 

 

 

 

 

./ToolTestQtOcrWidget/qtocrwidget.cpp

 

#pragma GCC diagnostic push
#pragma GCC diagnostic ignored "-Weffc++"
#include "qtocrwidget.h"

#include <QFile>

#include "ocr.h"
#pragma GCC diagnostic pop

QtOcrWidget::QtOcrWidget(
  const std::string& datafile,
  const std::string& whitelist,
  QWidget *parent)
  : QtSketchWidget(parent),
    m_ocr(new Ocr(datafile,whitelist))
{
  //assert(QFile::exists(datafile.c_str())); //Tesseract adds path
}

const std::string QtOcrWidget::Read() const
{
  QImage copy = const_cast<QtOcrWidget*>(this)->grab().toImage();
  //QImage copy = QPixmap::grabWidget(const_cast<QtOcrWidget*>(this)).toImage();
  copy.save("QtOcrWidget.png");
  const std::string text = m_ocr->Read(
    copy.bits(),
    copy.depth() / 8, //Convert bit to byte
    copy.bytesPerLine(),
    0, //left
    0, //top
    copy.width(),
    copy.height());
  return text;
}

 

 

 

 

 

./ToolTestQtOcrWidget/qtsketchwidget.h

 

#ifndef QTSKETCHWIDGET_H
#define QTSKETCHWIDGET_H

#include <QWidget>

///Qt example
class QtSketchWidget : public QWidget
{
  Q_OBJECT
public:
  explicit QtSketchWidget(QWidget *parent = 0);
  void clear();
  virtual ~QtSketchWidget() {}

protected:
  void mouseMoveEvent(QMouseEvent *);
  void mousePressEvent(QMouseEvent *);
  void paintEvent(QPaintEvent *);

private:
  std::vector<std::vector<QPoint> > m_points;
signals:

public slots:

};

#endif // QTSKETCHWIDGET_H

 

 

 

 

 

./ToolTestQtOcrWidget/qtsketchwidget.cpp

 

#pragma GCC diagnostic push
#pragma GCC diagnostic ignored "-Weffc++"
#include "qtsketchwidget.h"

#include <cassert>

#include <QMouseEvent>
#include <QPainter>
#include <QSysInfo>
#pragma GCC diagnostic pop


QtSketchWidget::QtSketchWidget(QWidget *parent)
  : QWidget(parent)
{
  this->setMouseTracking(true);
}

void QtSketchWidget::clear()
{
  m_points.clear();
  this->repaint();
}

void QtSketchWidget::mouseMoveEvent(QMouseEvent * e)
{
  if (e->buttons() & Qt::LeftButton)
  {
    m_points.back().push_back(e->pos());
    this->repaint();
  }
}

void QtSketchWidget::mousePressEvent(QMouseEvent * e)
{
  if (e->buttons() & Qt::LeftButton)
  {
    m_points.push_back(std::vector<QPoint>());
    m_points.back().push_back(e->pos());
  }
}

void QtSketchWidget::paintEvent(QPaintEvent *)
{
  QPainter painter(this);
  {
    QPen pen = painter.pen();
    pen.setCapStyle(Qt::RoundCap);
    pen.setColor(Qt::gray);
    pen.setWidth(10);
    painter.setPen(pen);
  }

  const int n_lines = static_cast<int>(m_points.size());
  for (int line=0; line!=n_lines; ++line)
  {
    const std::vector<QPoint>& points = m_points[line];
    const int n_points = static_cast<int>(points.size());
    for (int point=1; point!=n_points; ++point)
    {
      painter.drawLine(points[point-1],points[point]);
    }
  }
}

 

 

 

 

 

./ToolTestQtOcrWidget/tesseracthelper.h

 

#ifndef TESSERACTHELPER_H
#define TESSERACTHELPER_H

#include <string>

//These functions must be in the global namespace,
//because tesseract assumes these exist in the
//namespace-absent C header files
#include <signal.h>
#include <unistd.h>

#define BILDERBIKKEL_FIX_COMPILER_ERROR_CREATEPROCESS

#define BILDERBIKKEL_REMOVE_FSYNC
#define BILDERBIKKEL_REMOVE_OTHER_MAIN
#define BILDERBIKKEL_REMOVE_SLEEP

//Call of Linux fork() or the Windows equivalent
#define BILDERBIKKEL_REMOVE_SVSYNCH_STARTPROCESS_SVUTIL_CPP

//Call of Linux fork() or the Windows equivalent
#define BILDERBIKKEL_REMOVE_SVNETWORK_RECEIVE_SVUTIL_CPP

#define BILDERBIKKEL_REMOVE_USELESS_GLOBAL_DEMODIR

#ifndef BILDERBIKKEL_STRTOK_R_ALREADY_DEFINED
#define strtok_r(s, d, p) strtok(s, d)
#endif

long int Nrand48(unsigned short int xsubi[3]);

#ifndef M_PI
#define M_PI 3.14159265359
#endif

#endif // TESSERACTHELPER_H

 

 

 

 

 

./ToolTestQtOcrWidget/tesseracthelper.cpp

 

#pragma GCC diagnostic push
#pragma GCC diagnostic ignored "-Weffc++"
#include "tesseracthelper.h"

#include <cstdlib>
#include <limits>
#include <stdlib.h>
#include <stdint.h>
#pragma GCC diagnostic pop

//Identical to UNIX nrand48
long int Nrand48(unsigned short int xsubi[3])
{
  static unsigned long long int a = 0x5deece66dull;
  static unsigned short int c = 0xb;
  const uint64_t x
    = static_cast<uint64_t>(xsubi[2]) << 32
    | static_cast<uint32_t>(xsubi[1]) << 16
    | xsubi[0];
  const uint64_t y = x * a + c;

  xsubi[0] = y & 0xffff;
  xsubi[1] = (y >> 16) & 0xffff;
  xsubi[2] = (y >> 32) & 0xffff;

  if (sizeof(unsigned short int) == 2)
  {
    return xsubi[2] << 15 | xsubi[1] >> 1;
  }
  else
  {
    return xsubi[2] >> 1;
  }
}

//Used by the original program
//uinT32 nrand48(               //get random number
//               uinT16 *seeds  //seeds to use
//              ) {
//  static uinT32 seed = 0;        //only seed
//
//  if (seed == 0) {
//    seed = seeds[0] ^ (seeds[1] << 8) ^ (seeds[2] << 16);
//    srand(seed);
//  }
//                                 //make 32 bit one
//  return rand () | (rand () << 16);
//}

 

 

 

 

 

Go back to Richel Bilderbeek's C++ page.

Go back to Richel Bilderbeek's homepage.

 

Valid XHTML 1.0 Strict

This page has been created by the tool CodeToHtml