mirror of
https://github.com/tesseract-ocr/tesseract.git
synced 2024-11-27 12:49:35 +08:00
Use Leptonica API to access internals of Box
Signed-off-by: Stefan Weil <sw@weilnetz.de>
This commit is contained in:
parent
0df584e65d
commit
8ecaad56e3
@ -84,8 +84,10 @@ void BoxChar::TranslateBoxes(int xshift, int yshift, std::vector<BoxChar *> *box
|
||||
for (auto &boxe : *boxes) {
|
||||
Box *box = boxe->box_;
|
||||
if (box != nullptr) {
|
||||
box->x += xshift;
|
||||
box->y += yshift;
|
||||
int32_t box_x;
|
||||
int32_t box_y;
|
||||
boxGetGeometry(box, &box_x, &box_y, nullptr, nullptr);
|
||||
boxSetGeometry(box, box_x + xshift, box_y + yshift, -1, -1);
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -129,10 +131,18 @@ void BoxChar::InsertNewlines(bool rtl_rules, bool vertical_rules, std::vector<Bo
|
||||
continue;
|
||||
}
|
||||
if (prev_i != SIZE_MAX) {
|
||||
int32_t box_x;
|
||||
int32_t box_y;
|
||||
boxGetGeometry(box, &box_x, &box_y, nullptr, nullptr);
|
||||
Box *prev_box = (*boxes)[prev_i]->box_;
|
||||
int shift = box->x - prev_box->x;
|
||||
int32_t prev_box_x;
|
||||
int32_t prev_box_y;
|
||||
int32_t prev_box_w;
|
||||
int32_t prev_box_h;
|
||||
boxGetGeometry(prev_box, &prev_box_x, &prev_box_y, &prev_box_w, &prev_box_h);
|
||||
int shift = box_x - prev_box_x;
|
||||
if (vertical_rules) {
|
||||
shift = box->y - prev_box->y;
|
||||
shift = box_y - prev_box_y;
|
||||
} else if (rtl_rules) {
|
||||
shift = -shift;
|
||||
}
|
||||
@ -142,15 +152,15 @@ void BoxChar::InsertNewlines(bool rtl_rules, bool vertical_rules, std::vector<Bo
|
||||
// a box outside the image by making the width and height 1.
|
||||
int width = 1;
|
||||
int height = 1;
|
||||
int x = prev_box->x + prev_box->w;
|
||||
int y = prev_box->y;
|
||||
int x = prev_box_x + prev_box_w;
|
||||
int y = prev_box_y;
|
||||
if (vertical_rules) {
|
||||
x = prev_box->x;
|
||||
y = prev_box->y + prev_box->h;
|
||||
x = prev_box_x;
|
||||
y = prev_box_y + prev_box_h;
|
||||
} else if (rtl_rules) {
|
||||
x = prev_box->x - width;
|
||||
x = prev_box_x - width;
|
||||
if (x < 0) {
|
||||
tprintf("prev x = %d, width=%d\n", prev_box->x, width);
|
||||
tprintf("prev x = %d, width=%d\n", prev_box_x, width);
|
||||
x = 0;
|
||||
}
|
||||
}
|
||||
@ -184,27 +194,38 @@ void BoxChar::InsertSpaces(bool rtl_rules, bool vertical_rules, std::vector<BoxC
|
||||
if (box == nullptr) {
|
||||
Box *prev = (*boxes)[i - 1]->box_;
|
||||
Box *next = (*boxes)[i + 1]->box_;
|
||||
int32_t prev_x;
|
||||
int32_t prev_y;
|
||||
int32_t prev_w;
|
||||
int32_t prev_h;
|
||||
int32_t next_x;
|
||||
int32_t next_y;
|
||||
int32_t next_w;
|
||||
int32_t next_h;
|
||||
ASSERT_HOST(prev != nullptr && next != nullptr);
|
||||
int top = std::min(prev->y, next->y);
|
||||
int bottom = std::max(prev->y + prev->h, next->y + next->h);
|
||||
int left = prev->x + prev->w;
|
||||
int right = next->x;
|
||||
boxGetGeometry(prev, &prev_x, &prev_y, &prev_w, &prev_h);
|
||||
boxGetGeometry(next, &next_x, &next_y, &next_w, &next_h);
|
||||
int top = std::min(prev_y, next_y);
|
||||
int bottom = std::max(prev_y + prev_h, next_y + next_h);
|
||||
int left = prev_x + prev_w;
|
||||
int right = next_x;
|
||||
if (vertical_rules) {
|
||||
top = prev->y + prev->h;
|
||||
bottom = next->y;
|
||||
left = std::min(prev->x, next->x);
|
||||
right = std::max(prev->x + prev->w, next->x + next->w);
|
||||
top = prev_y + prev_h;
|
||||
bottom = next_y;
|
||||
left = std::min(prev_x, next_x);
|
||||
right = std::max(prev_x + prev_w, next_x + next_w);
|
||||
} else if (rtl_rules) {
|
||||
// With RTL we have to account for BiDi.
|
||||
// Right becomes the min left of all prior boxes back to the first
|
||||
// space or newline.
|
||||
right = prev->x;
|
||||
left = next->x + next->w;
|
||||
right = prev_x;
|
||||
left = next_x + next_w;
|
||||
for (int j = i - 2; j >= 0 && (*boxes)[j]->ch_ != " " && (*boxes)[j]->ch_ != "\t"; --j) {
|
||||
prev = (*boxes)[j]->box_;
|
||||
ASSERT_HOST(prev != nullptr);
|
||||
if (prev->x < right) {
|
||||
right = prev->x;
|
||||
boxGetGeometry(prev, &prev_x, nullptr, nullptr, nullptr);
|
||||
if (prev_x < right) {
|
||||
right = prev_x;
|
||||
}
|
||||
}
|
||||
// Left becomes the max right of all next boxes forward to the first
|
||||
@ -212,8 +233,9 @@ void BoxChar::InsertSpaces(bool rtl_rules, bool vertical_rules, std::vector<BoxC
|
||||
for (size_t j = i + 2;
|
||||
j < boxes->size() && (*boxes)[j]->box_ != nullptr && (*boxes)[j]->ch_ != "\t"; ++j) {
|
||||
next = (*boxes)[j]->box_;
|
||||
if (next->x + next->w > left) {
|
||||
left = next->x + next->w;
|
||||
boxGetGeometry(next, &next_x, nullptr, &next_w, nullptr);
|
||||
if (next_x + next_w > left) {
|
||||
left = next_x + next_w;
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -275,8 +297,14 @@ bool BoxChar::MostlyVertical(const std::vector<BoxChar *> &boxes) {
|
||||
for (size_t i = 1; i < boxes.size(); ++i) {
|
||||
if (boxes[i - 1]->box_ != nullptr && boxes[i]->box_ != nullptr &&
|
||||
boxes[i - 1]->page_ == boxes[i]->page_) {
|
||||
int dx = boxes[i]->box_->x - boxes[i - 1]->box_->x;
|
||||
int dy = boxes[i]->box_->y - boxes[i - 1]->box_->y;
|
||||
int32_t x0;
|
||||
int32_t y0;
|
||||
boxGetGeometry(boxes[i]->box_, &x0, &y0, nullptr, nullptr);
|
||||
int32_t x1;
|
||||
int32_t y1;
|
||||
boxGetGeometry(boxes[i - 1]->box_, &x1, &y1, nullptr, nullptr);
|
||||
int dx = x0 - x1;
|
||||
int dy = y0 - y1;
|
||||
if (abs(dx) > abs(dy) * kMinNewlineRatio || abs(dy) > abs(dx) * kMinNewlineRatio) {
|
||||
total_dx += dx * dx;
|
||||
total_dy += dy * dy;
|
||||
@ -337,8 +365,14 @@ std::string BoxChar::GetTesseractBoxStr(int height, const std::vector<BoxChar *>
|
||||
tprintf("Error: Call PrepareToWrite before WriteTesseractBoxFile!!\n");
|
||||
return "";
|
||||
}
|
||||
int nbytes = snprintf(buffer, kMaxLineLength, "%s %d %d %d %d %d\n", boxe->ch_.c_str(), box->x,
|
||||
height - box->y - box->h, box->x + box->w, height - box->y, boxe->page_);
|
||||
int32_t box_x;
|
||||
int32_t box_y;
|
||||
int32_t box_w;
|
||||
int32_t box_h;
|
||||
boxGetGeometry(const_cast<Box *>(box), &box_x, &box_y, &box_w, &box_h);
|
||||
int nbytes = snprintf(buffer, kMaxLineLength, "%s %d %d %d %d %d\n",
|
||||
boxe->ch_.c_str(), box_x, height - box_y - box_h,
|
||||
box_x + box_w, height - box_y, boxe->page_);
|
||||
output.append(buffer, nbytes);
|
||||
}
|
||||
return output;
|
||||
|
@ -26,9 +26,6 @@
|
||||
#include <vector>
|
||||
|
||||
#include <allheaders.h> // for Leptonica API
|
||||
#if (LIBLEPT_MAJOR_VERSION == 1 && LIBLEPT_MINOR_VERSION >= 83) || LIBLEPT_MAJOR_VERSION > 1
|
||||
#include <pix_internal.h> // for fast access to Box geometry
|
||||
#endif
|
||||
#include <tesseract/export.h>
|
||||
|
||||
namespace tesseract {
|
||||
@ -79,7 +76,11 @@ public:
|
||||
if (other.box_ == nullptr) {
|
||||
return false;
|
||||
}
|
||||
return box_->x < other.box_->x;
|
||||
int32_t box_x;
|
||||
int32_t other_box_x;
|
||||
boxGetGeometry(box_, &box_x, nullptr, nullptr, nullptr);
|
||||
boxGetGeometry(other.box_, &other_box_x, nullptr, nullptr, nullptr);
|
||||
return box_x < other_box_x;
|
||||
}
|
||||
// Increments *num_rtl and *num_ltr according to the directionality of
|
||||
// characters in the box.
|
||||
|
@ -428,15 +428,25 @@ static void MergeBoxCharsToWords(std::vector<BoxChar *> *boxchars) {
|
||||
BoxChar *last_boxchar = result.back();
|
||||
// Compute bounding box union
|
||||
const Box *box = boxchar->box();
|
||||
int32_t box_x;
|
||||
int32_t box_y;
|
||||
int32_t box_w;
|
||||
int32_t box_h;
|
||||
boxGetGeometry(const_cast<Box *>(box), &box_x, &box_y, &box_w, &box_h);
|
||||
Box *last_box = last_boxchar->mutable_box();
|
||||
int left = std::min(last_box->x, box->x);
|
||||
int right = std::max(last_box->x + last_box->w, box->x + box->w);
|
||||
int top = std::min(last_box->y, box->y);
|
||||
int bottom = std::max(last_box->y + last_box->h, box->y + box->h);
|
||||
int32_t last_box_x;
|
||||
int32_t last_box_y;
|
||||
int32_t last_box_w;
|
||||
int32_t last_box_h;
|
||||
boxGetGeometry(last_box, &last_box_x, &last_box_y, &last_box_w, &last_box_h);
|
||||
int left = std::min(last_box_x, box_x);
|
||||
int right = std::max(last_box_x + last_box_w, box_x + box_w);
|
||||
int top = std::min(last_box_y, box_y);
|
||||
int bottom = std::max(last_box_y + last_box_h, box_y + box_h);
|
||||
// Conclude that the word was broken to span multiple lines based on the
|
||||
// size of the merged bounding box in relation to those of the individual
|
||||
// characters seen so far.
|
||||
if (right - left > last_box->w + 5 * box->w) {
|
||||
if (right - left > last_box_w + 5 * box_w) {
|
||||
tlog(1, "Found line break after '%s'", last_boxchar->ch().c_str());
|
||||
// Insert a fake interword space and start a new word with the current
|
||||
// boxchar.
|
||||
@ -447,10 +457,7 @@ static void MergeBoxCharsToWords(std::vector<BoxChar *> *boxchars) {
|
||||
}
|
||||
// Append to last word
|
||||
last_boxchar->mutable_ch()->append(boxchar->ch());
|
||||
last_box->x = left;
|
||||
last_box->w = right - left;
|
||||
last_box->y = top;
|
||||
last_box->h = bottom - top;
|
||||
boxSetGeometry(last_box, left, top, right - left, bottom - top);
|
||||
delete boxchar;
|
||||
boxchar = nullptr;
|
||||
}
|
||||
|
@ -282,12 +282,18 @@ static void ExtractFontProperties(const std::string &utf8_text, StringRenderer *
|
||||
if (IsWhitespaceBox(boxes[b + 1])) {
|
||||
continue;
|
||||
}
|
||||
int xgap = (boxes[b + 1]->box()->x - (boxes[b]->box()->x + boxes[b]->box()->w));
|
||||
int32_t box_x;
|
||||
int32_t box_w;
|
||||
boxGetGeometry(const_cast<Box *>(boxes[b]->box()), &box_x, nullptr, &box_w, nullptr);
|
||||
int32_t box1_x;
|
||||
int32_t box1_w;
|
||||
boxGetGeometry(const_cast<Box *>(boxes[b + 1]->box()), &box1_x, nullptr, &box1_w, nullptr);
|
||||
int xgap = (box1_x - (box_x + box_w));
|
||||
spacing_map_it0 = spacing_map.find(ch0);
|
||||
int ok_count = 0;
|
||||
if (spacing_map_it0 == spacing_map.end() &&
|
||||
render->font().GetSpacingProperties(ch0, &x_bearing, &x_advance)) {
|
||||
spacing_map[ch0] = SpacingProperties(x_bearing, x_advance - x_bearing - boxes[b]->box()->w);
|
||||
spacing_map[ch0] = SpacingProperties(x_bearing, x_advance - x_bearing - box_w);
|
||||
spacing_map_it0 = spacing_map.find(ch0);
|
||||
++ok_count;
|
||||
}
|
||||
@ -297,7 +303,7 @@ static void ExtractFontProperties(const std::string &utf8_text, StringRenderer *
|
||||
if (spacing_map_it1 == spacing_map.end() &&
|
||||
render->font().GetSpacingProperties(ch1, &x_bearing, &x_advance)) {
|
||||
spacing_map[ch1] =
|
||||
SpacingProperties(x_bearing, x_advance - x_bearing - boxes[b + 1]->box()->w);
|
||||
SpacingProperties(x_bearing, x_advance - x_bearing - box1_w);
|
||||
spacing_map_it1 = spacing_map.find(ch1);
|
||||
++ok_count;
|
||||
}
|
||||
@ -356,10 +362,11 @@ static bool MakeIndividualGlyphs(Image pix, const std::vector<BoxChar *> &vbox,
|
||||
if (!b) {
|
||||
continue;
|
||||
}
|
||||
const int x = b->x;
|
||||
const int y = b->y;
|
||||
const int w = b->w;
|
||||
const int h = b->h;
|
||||
int32_t x;
|
||||
int32_t y;
|
||||
int32_t w;
|
||||
int32_t h;
|
||||
boxGetGeometry(b, &x, &y, &w, &h);
|
||||
// Check present tiff page (for multipage tiff)
|
||||
if (y < y_previous - pixGetHeight(pix) / 10) {
|
||||
tprintf("ERROR: Wrap-around encountered, at i=%d\n", i);
|
||||
|
Loading…
Reference in New Issue
Block a user