mirror of
https://github.com/tesseract-ocr/tesseract.git
synced 2024-11-27 12:49:35 +08:00
This reverts commit122daf1d64
, reversing changes made to4cd56dc5f5
. Those changes caused two regressions which resulted in an assertion or a segmentation fault. Signed-off-by: Stefan Weil <sw@weilnetz.de>
This commit is contained in:
parent
e176169a90
commit
4df822a3fc
@ -284,7 +284,6 @@ noinst_HEADERS += src/ccstruct/seam.h
|
||||
noinst_HEADERS += src/ccstruct/split.h
|
||||
noinst_HEADERS += src/ccstruct/statistc.h
|
||||
noinst_HEADERS += src/ccstruct/stepblob.h
|
||||
noinst_HEADERS += src/ccstruct/tabletransfer.h
|
||||
noinst_HEADERS += src/ccstruct/werd.h
|
||||
if !DISABLED_LEGACY_ENGINE
|
||||
noinst_HEADERS += src/ccstruct/fontinfo.h
|
||||
|
@ -32,7 +32,6 @@
|
||||
#include <tesseract/version.h>
|
||||
|
||||
#include <cstdio>
|
||||
#include <tuple> // for std::tuple
|
||||
#include <vector> // for std::vector
|
||||
|
||||
struct Pix;
|
||||
@ -539,31 +538,6 @@ public:
|
||||
*/
|
||||
char *GetUTF8Text();
|
||||
|
||||
size_t GetNumberOfTables() const;
|
||||
|
||||
/// Return the i-th table bounding box coordinates
|
||||
///
|
||||
/// Gives the (top_left.x, top_left.y, bottom_right.x, bottom_right.y)
|
||||
/// coordinates of the i-th table.
|
||||
std::tuple<int, int, int, int> GetTableBoundingBox(
|
||||
unsigned
|
||||
i ///< Index of the table, for upper limit \see GetNumberOfTables()
|
||||
);
|
||||
|
||||
/// Get bounding boxes of the rows of a table
|
||||
/// return values are (top_left.x, top_left.y, bottom_right.x, bottom_right.y)
|
||||
std::vector<std::tuple<int, int, int, int> > GetTableRows(
|
||||
unsigned
|
||||
i ///< Index of the table, for upper limit \see GetNumberOfTables()
|
||||
);
|
||||
|
||||
/// Get bounding boxes of the cols of a table
|
||||
/// return values are (top_left.x, top_left.y, bottom_right.x, bottom_right.y)
|
||||
std::vector<std::tuple<int, int, int, int> > GetTableCols(
|
||||
unsigned
|
||||
i ///< Index of the table, for upper limit \see GetNumberOfTables()
|
||||
);
|
||||
|
||||
/**
|
||||
* Make a HTML-formatted string with hOCR markup from the internal
|
||||
* data structures.
|
||||
|
@ -56,7 +56,6 @@
|
||||
#include "tesseractclass.h" // for Tesseract
|
||||
#include "tprintf.h" // for tprintf
|
||||
#include "werd.h" // for WERD, WERD_IT, W_FUZZY_NON, W_FUZZY_SP
|
||||
#include "tabletransfer.h" // for detected tables from tablefind.h
|
||||
#include "thresholder.h" // for ImageThresholder
|
||||
|
||||
#include <tesseract/baseapi.h>
|
||||
@ -1370,66 +1369,6 @@ char *TessBaseAPI::GetUTF8Text() {
|
||||
return result;
|
||||
}
|
||||
|
||||
size_t TessBaseAPI::GetNumberOfTables() const
|
||||
{
|
||||
return constUniqueInstance<std::vector<TessTable>>().size();
|
||||
}
|
||||
|
||||
std::tuple<int,int,int,int> TessBaseAPI::GetTableBoundingBox(unsigned i)
|
||||
{
|
||||
const auto &t = constUniqueInstance<std::vector<TessTable>>();
|
||||
|
||||
if (i >= t.size()) {
|
||||
return std::tuple<int, int, int, int>(0, 0, 0, 0);
|
||||
}
|
||||
|
||||
const int height = tesseract_->ImageHeight();
|
||||
|
||||
return std::make_tuple<int,int,int,int>(
|
||||
t[i].box.left(), height - t[i].box.top(),
|
||||
t[i].box.right(), height - t[i].box.bottom());
|
||||
}
|
||||
|
||||
std::vector<std::tuple<int,int,int,int>> TessBaseAPI::GetTableRows(unsigned i)
|
||||
{
|
||||
const auto &t = constUniqueInstance<std::vector<TessTable>>();
|
||||
|
||||
if (i >= t.size()) {
|
||||
return std::vector<std::tuple<int, int, int, int>>();
|
||||
}
|
||||
|
||||
std::vector<std::tuple<int,int,int,int>> rows(t[i].rows.size());
|
||||
const int height = tesseract_->ImageHeight();
|
||||
|
||||
for (unsigned j = 0; j < t[i].rows.size(); ++j) {
|
||||
rows[j] =
|
||||
std::make_tuple<int, int, int, int>(t[i].rows[j].left(), height - t[i].rows[j].top(),
|
||||
t[i].rows[j].right(), height - t[i].rows[j].bottom());
|
||||
}
|
||||
|
||||
return rows;
|
||||
}
|
||||
|
||||
std::vector<std::tuple<int,int,int,int> > TessBaseAPI::GetTableCols(unsigned i)
|
||||
{
|
||||
const auto &t = constUniqueInstance<std::vector<TessTable>>();
|
||||
|
||||
if (i >= t.size()) {
|
||||
return std::vector<std::tuple<int, int, int, int>>();
|
||||
}
|
||||
|
||||
std::vector<std::tuple<int,int,int,int>> cols(t[i].cols.size());
|
||||
const int height = tesseract_->ImageHeight();
|
||||
|
||||
for (unsigned j = 0; j < t[i].cols.size(); ++j) {
|
||||
cols[j] =
|
||||
std::make_tuple<int, int, int, int>(t[i].cols[j].left(), height - t[i].cols[j].top(),
|
||||
t[i].cols[j].right(), height - t[i].cols[j].bottom());
|
||||
}
|
||||
|
||||
return cols;
|
||||
}
|
||||
|
||||
static void AddBoxToTSV(const PageIterator *it, PageIteratorLevel level, std::string &text) {
|
||||
int left, top, right, bottom;
|
||||
it->BoundingBox(level, &left, &top, &right, &bottom);
|
||||
@ -2252,8 +2191,6 @@ void TessBaseAPI::ClearResults() {
|
||||
delete paragraph_models_;
|
||||
paragraph_models_ = nullptr;
|
||||
}
|
||||
|
||||
uniqueInstance<std::vector<TessTable>>().clear();
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -1,67 +0,0 @@
|
||||
/******************************************************************************
|
||||
* File: tabletransfer.h
|
||||
* Description: Infrastructure for the transfer of table detection results
|
||||
* Author: Stefan Brechtken
|
||||
*
|
||||
* (C) Copyright 2021, Stefan Brechtken
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
#ifndef TESSERACT_CCSTRUCT_TABLETRANSFER_H_
|
||||
#define TESSERACT_CCSTRUCT_TABLETRANSFER_H_
|
||||
#include <memory>
|
||||
#include <vector>
|
||||
#include "rect.h"
|
||||
|
||||
namespace tesseract {
|
||||
|
||||
/// Structure for data transfer from table detector
|
||||
struct TessTable {
|
||||
tesseract::TBOX box;
|
||||
std::vector<tesseract::TBOX> rows;
|
||||
std::vector<tesseract::TBOX> cols;
|
||||
};
|
||||
|
||||
/** \brief You can use this small template function to ensure that one and
|
||||
* only one object of type T exists. It implements the Singleton Pattern.
|
||||
*
|
||||
* T must be default-constructable.
|
||||
* Usage examples:
|
||||
* A& a = uniqueInstance<A>();
|
||||
* a.xyz();
|
||||
* uniqueInstance<A>(make_unique<A>(42)); // replace instance
|
||||
* a.foo();
|
||||
* or
|
||||
* uniqueInstance<A>().xyz();
|
||||
*/
|
||||
template<typename T>
|
||||
T& uniqueInstance(std::unique_ptr<T> new_instance = nullptr)
|
||||
{
|
||||
static std::unique_ptr<T> _instance = std::make_unique<T>();
|
||||
|
||||
if (new_instance) {
|
||||
_instance = std::move(new_instance);
|
||||
}
|
||||
|
||||
return *_instance.get();
|
||||
}
|
||||
|
||||
/// return const version of \see uniqueInstance
|
||||
template<typename T>
|
||||
const T& constUniqueInstance(std::unique_ptr<T> new_instance = nullptr)
|
||||
{
|
||||
return uniqueInstance<T>(std::move(new_instance));
|
||||
}
|
||||
|
||||
} // namespace tesseract
|
||||
|
||||
#endif // TESSERACT_CCSTRUCT_TABLETRANSFER_H_
|
@ -38,7 +38,6 @@
|
||||
#include "strokewidth.h"
|
||||
#include "tablefind.h"
|
||||
#include "workingpartset.h"
|
||||
#include "tabletransfer.h"
|
||||
|
||||
#include <algorithm>
|
||||
|
||||
@ -1591,11 +1590,6 @@ void ColumnFinder::RotateAndReskewBlocks(bool input_is_rtl, TO_BLOCK_LIST *block
|
||||
tprintf("Block median size = (%d, %d)\n", block->median_size().x(), block->median_size().y());
|
||||
}
|
||||
}
|
||||
|
||||
auto &tables = uniqueInstance<std::vector<TessTable>>();
|
||||
for (TessTable &mt : tables) {
|
||||
mt.box.rotate_large(reskew_);
|
||||
}
|
||||
}
|
||||
|
||||
// Computes the rotations for the block (to make textlines horizontal) and
|
||||
|
@ -28,7 +28,6 @@
|
||||
|
||||
#include "colpartitionset.h"
|
||||
#include "tablerecog.h"
|
||||
#include "tabletransfer.h"
|
||||
|
||||
namespace tesseract {
|
||||
|
||||
@ -263,13 +262,12 @@ void TableFinder::LocateTables(ColPartitionGrid *grid, ColPartitionSet **all_col
|
||||
|
||||
#ifndef GRAPHICS_DISABLED
|
||||
if (textord_show_tables) {
|
||||
ScrollView *table_win = MakeWindow(0, 300,
|
||||
"Step 1: Column Partitions & Neighbors");
|
||||
ScrollView *table_win = MakeWindow(0, 300, "Column Partitions & Neighbors");
|
||||
DisplayColPartitions(table_win, &clean_part_grid_, ScrollView::BLUE);
|
||||
DisplayColPartitions(table_win, &leader_and_ruling_grid_, ScrollView::AQUAMARINE);
|
||||
DisplayColPartitionConnections(table_win, &clean_part_grid_, ScrollView::ORANGE);
|
||||
|
||||
table_win = MakeWindow(100, 300, "Step 2: Fragmented Text");
|
||||
table_win = MakeWindow(100, 300, "Fragmented Text");
|
||||
DisplayColPartitions(table_win, &fragmented_text_grid_, ScrollView::BLUE);
|
||||
}
|
||||
#endif // !GRAPHICS_DISABLED
|
||||
@ -304,8 +302,7 @@ void TableFinder::LocateTables(ColPartitionGrid *grid, ColPartitionSet **all_col
|
||||
|
||||
#ifndef GRAPHICS_DISABLED
|
||||
if (textord_tablefind_show_mark) {
|
||||
ScrollView *table_win = MakeWindow(1200, 300,
|
||||
"Step 7: Table Columns and Regions");
|
||||
ScrollView *table_win = MakeWindow(1200, 300, "Table Columns and Regions");
|
||||
DisplayColSegments(table_win, &table_columns, ScrollView::DARK_TURQUOISE);
|
||||
DisplayColSegments(table_win, &table_regions, ScrollView::YELLOW);
|
||||
}
|
||||
@ -327,8 +324,7 @@ void TableFinder::LocateTables(ColPartitionGrid *grid, ColPartitionSet **all_col
|
||||
|
||||
#ifndef GRAPHICS_DISABLED
|
||||
if (textord_show_tables) {
|
||||
ScrollView *table_win = MakeWindow(1200, 300,
|
||||
"Step 8: Detected Table Locations");
|
||||
ScrollView *table_win = MakeWindow(1200, 300, "Detected Table Locations");
|
||||
DisplayColPartitions(table_win, &clean_part_grid_, ScrollView::BLUE);
|
||||
DisplayColSegments(table_win, &table_columns, ScrollView::KHAKI);
|
||||
table_grid_.DisplayBoxes(table_win);
|
||||
@ -342,10 +338,8 @@ void TableFinder::LocateTables(ColPartitionGrid *grid, ColPartitionSet **all_col
|
||||
|
||||
#ifndef GRAPHICS_DISABLED
|
||||
if (textord_show_tables) {
|
||||
ScrollView *table_win = MakeWindow(1400, 600,
|
||||
"Step 10: Recognized Tables");
|
||||
DisplayColPartitions(table_win, &clean_part_grid_,
|
||||
ScrollView::BLUE, ScrollView::BLUE);
|
||||
ScrollView *table_win = MakeWindow(1400, 600, "Recognized Tables");
|
||||
DisplayColPartitions(table_win, &clean_part_grid_, ScrollView::BLUE, ScrollView::BLUE);
|
||||
table_grid_.DisplayBoxes(table_win);
|
||||
}
|
||||
#endif // !GRAPHICS_DISABLED
|
||||
@ -358,9 +352,8 @@ void TableFinder::LocateTables(ColPartitionGrid *grid, ColPartitionSet **all_col
|
||||
|
||||
#ifndef GRAPHICS_DISABLED
|
||||
if (textord_show_tables) {
|
||||
ScrollView *table_win = MakeWindow(1500, 300, "Step 11: Detected Tables");
|
||||
DisplayColPartitions(table_win, &clean_part_grid_,
|
||||
ScrollView::BLUE, ScrollView::BLUE);
|
||||
ScrollView *table_win = MakeWindow(1500, 300, "Detected Tables");
|
||||
DisplayColPartitions(table_win, &clean_part_grid_, ScrollView::BLUE, ScrollView::BLUE);
|
||||
table_grid_.DisplayBoxes(table_win);
|
||||
}
|
||||
#endif // !GRAPHICS_DISABLED
|
||||
@ -782,8 +775,7 @@ void TableFinder::MarkTablePartitions() {
|
||||
MarkPartitionsUsingLocalInformation();
|
||||
#ifndef GRAPHICS_DISABLED
|
||||
if (textord_tablefind_show_mark) {
|
||||
ScrollView *table_win = MakeWindow(300, 300,
|
||||
"Step 3: Initial Table Partitions");
|
||||
ScrollView *table_win = MakeWindow(300, 300, "Initial Table Partitions");
|
||||
DisplayColPartitions(table_win, &clean_part_grid_, ScrollView::BLUE);
|
||||
DisplayColPartitions(table_win, &leader_and_ruling_grid_, ScrollView::AQUAMARINE);
|
||||
}
|
||||
@ -791,8 +783,7 @@ void TableFinder::MarkTablePartitions() {
|
||||
FilterFalseAlarms();
|
||||
#ifndef GRAPHICS_DISABLED
|
||||
if (textord_tablefind_show_mark) {
|
||||
ScrollView *table_win = MakeWindow(600, 300,
|
||||
"Step 4: Filtered Table Partitions");
|
||||
ScrollView *table_win = MakeWindow(600, 300, "Filtered Table Partitions");
|
||||
DisplayColPartitions(table_win, &clean_part_grid_, ScrollView::BLUE);
|
||||
DisplayColPartitions(table_win, &leader_and_ruling_grid_, ScrollView::AQUAMARINE);
|
||||
}
|
||||
@ -800,8 +791,7 @@ void TableFinder::MarkTablePartitions() {
|
||||
SmoothTablePartitionRuns();
|
||||
#ifndef GRAPHICS_DISABLED
|
||||
if (textord_tablefind_show_mark) {
|
||||
ScrollView *table_win = MakeWindow(900, 300,
|
||||
"Step 5: Smoothed Table Partitions");
|
||||
ScrollView *table_win = MakeWindow(900, 300, "Smoothed Table Partitions");
|
||||
DisplayColPartitions(table_win, &clean_part_grid_, ScrollView::BLUE);
|
||||
DisplayColPartitions(table_win, &leader_and_ruling_grid_, ScrollView::AQUAMARINE);
|
||||
}
|
||||
@ -809,8 +799,7 @@ void TableFinder::MarkTablePartitions() {
|
||||
FilterFalseAlarms();
|
||||
#ifndef GRAPHICS_DISABLED
|
||||
if (textord_tablefind_show_mark || textord_show_tables) {
|
||||
ScrollView *table_win = MakeWindow(900, 300,
|
||||
"Step 6: Final Table Partitions");
|
||||
ScrollView *table_win = MakeWindow(900, 300, "Final Table Partitions");
|
||||
DisplayColPartitions(table_win, &clean_part_grid_, ScrollView::BLUE);
|
||||
DisplayColPartitions(table_win, &leader_and_ruling_grid_, ScrollView::AQUAMARINE);
|
||||
}
|
||||
@ -1842,7 +1831,7 @@ void TableFinder::RecognizeTables() {
|
||||
#ifndef GRAPHICS_DISABLED
|
||||
ScrollView *table_win = nullptr;
|
||||
if (textord_show_tables) {
|
||||
table_win = MakeWindow(0, 0, "Step 9: Table Structure");
|
||||
table_win = MakeWindow(0, 0, "Table Structure");
|
||||
DisplayColPartitions(table_win, &fragmented_text_grid_, ScrollView::BLUE,
|
||||
ScrollView::LIGHT_BLUE);
|
||||
// table_grid_.DisplayBoxes(table_win);
|
||||
@ -1995,25 +1984,6 @@ void TableFinder::DisplayColPartitionConnections(ScrollView *win, ColPartitionGr
|
||||
// assigned to any table to their original types.
|
||||
void TableFinder::MakeTableBlocks(ColPartitionGrid *grid, ColPartitionSet **all_columns,
|
||||
WidthCallback width_cb) {
|
||||
#ifndef GRAPHICS_DISABLED
|
||||
ScrollView* table_win = nullptr;
|
||||
if (textord_show_tables) {
|
||||
table_win = MakeWindow(0, 0, "Step 12: Final tables");
|
||||
DisplayColPartitions(table_win, &fragmented_text_grid_,
|
||||
ScrollView::BLUE, ScrollView::LIGHT_BLUE);
|
||||
}
|
||||
#endif // GRAPHICS_DISABLED
|
||||
|
||||
// initializing recognizer in order to extract table row and columnd info
|
||||
TableRecognizer recognizer;
|
||||
{
|
||||
recognizer.Init();
|
||||
recognizer.set_line_grid(&leader_and_ruling_grid_);
|
||||
recognizer.set_text_grid(&fragmented_text_grid_);
|
||||
recognizer.set_max_text_height(global_median_xheight_ * 2.0);
|
||||
recognizer.set_min_height(1.5 * gridheight());
|
||||
}
|
||||
|
||||
// Since we have table blocks already, remove table tags from all
|
||||
// colpartitions
|
||||
GridSearch<ColPartition, ColPartition_CLIST, ColPartition_C_IT> gsearch(grid);
|
||||
@ -2068,30 +2038,8 @@ void TableFinder::MakeTableBlocks(ColPartitionGrid *grid, ColPartitionSet **all_
|
||||
table_partition->set_flow(BTFT_CHAIN);
|
||||
table_partition->SetBlobTypes();
|
||||
grid->InsertBBox(true, true, table_partition);
|
||||
|
||||
// Insert table columns and rows into an api accessible object
|
||||
StructuredTable* table_structure = recognizer.RecognizeTable(table_box);
|
||||
if (table_structure != nullptr) {
|
||||
#ifndef GRAPHICS_DISABLED
|
||||
if (textord_show_tables) {
|
||||
table_structure->Display(table_win, ScrollView::LIME_GREEN);
|
||||
}
|
||||
#endif // GRAPHICS_DISABLED
|
||||
|
||||
auto &tables = uniqueInstance<std::vector<TessTable>>();
|
||||
tables.push_back(
|
||||
TessTable{table_box, table_structure->getRows(), table_structure->getCols()});
|
||||
|
||||
delete table_structure;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#ifndef GRAPHICS_DISABLED
|
||||
if (textord_show_tables) {
|
||||
table_grid_.DisplayBoxes(table_win);
|
||||
}
|
||||
#endif // GRAPHICS_DISABLED
|
||||
}
|
||||
|
||||
//////// ColSegment code
|
||||
|
@ -310,39 +310,6 @@ void StructuredTable::Display(ScrollView *window, ScrollView::Color color) {
|
||||
|
||||
#endif
|
||||
|
||||
std::vector<TBOX> StructuredTable::getRows()
|
||||
{
|
||||
if (cell_y_.size() < 2) {
|
||||
return std::vector<TBOX>();
|
||||
}
|
||||
|
||||
std::vector<TBOX> rows(cell_y_.size() - 1);
|
||||
unsigned ct = cell_y_.size() - 2;
|
||||
for(unsigned i = 0; i + 1 < cell_y_.size(); i++) {
|
||||
const ICOORD left(bounding_box_.left(), cell_y_[i]);
|
||||
const ICOORD right(bounding_box_.right(), cell_y_[i + 1]);
|
||||
rows[ct - i] = TBOX(left, right);
|
||||
}
|
||||
|
||||
return rows;
|
||||
}
|
||||
|
||||
std::vector<TBOX> StructuredTable::getCols()
|
||||
{
|
||||
if (cell_x_.size() < 2) {
|
||||
return std::vector<TBOX>();
|
||||
}
|
||||
|
||||
std::vector<TBOX> cols(cell_x_.size() - 1);
|
||||
for(unsigned i = 0; i + 1 < cell_x_.size(); i++) {
|
||||
const ICOORD top(cell_x_[i], bounding_box_.top());
|
||||
const ICOORD bot(cell_x_[i+1], bounding_box_.bottom());
|
||||
cols[i] = TBOX(top, bot);
|
||||
}
|
||||
|
||||
return cols;
|
||||
}
|
||||
|
||||
// Clear structure information.
|
||||
void StructuredTable::ClearStructure() {
|
||||
cell_x_.clear();
|
||||
|
@ -2,7 +2,6 @@
|
||||
// File: tablerecog.h
|
||||
// Description: Functions to detect structure of tables.
|
||||
// Author: Nicholas Beato
|
||||
// Created: Aug 17, 2010
|
||||
//
|
||||
// (C) Copyright 2010, Google Inc.
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
@ -21,7 +20,6 @@
|
||||
#define TABLERECOG_H_
|
||||
|
||||
#include "colpartitiongrid.h"
|
||||
#include <vector>
|
||||
|
||||
namespace tesseract {
|
||||
|
||||
@ -136,11 +134,6 @@ public:
|
||||
// valid, the table and "best" grid lines are still drawn in the given color.
|
||||
void Display(ScrollView *window, ScrollView::Color color);
|
||||
|
||||
/// Calculate bounding boxes of the rows and return them.
|
||||
std::vector<TBOX> getRows();
|
||||
/// Calculate bounding boxes of the columns and return them.
|
||||
std::vector<TBOX> getCols();
|
||||
|
||||
protected:
|
||||
// Clear the structure information.
|
||||
void ClearStructure();
|
||||
|
Loading…
Reference in New Issue
Block a user