29 #include "config_auto.h"
32 #include "allheaders.h"
59 static Pix* RemoveEnclosingCircle(Pix* pixs) {
60 Pix* pixsi = pixInvert(
nullptr, pixs);
61 Pix* pixc = pixCreateTemplate(pixs);
62 pixSetOrClearBorder(pixc, 1, 1, 1, 1, PIX_SET);
63 pixSeedfillBinary(pixc, pixc, pixsi, 4);
64 pixInvert(pixc, pixc);
66 Pix* pixt = pixAnd(
nullptr, pixs, pixc);
68 pixCountConnComp(pixt, 8, &max_count);
70 l_int32 min_count = INT32_MAX;
71 Pix* pixout =
nullptr;
74 pixErodeBrick(pixc, pixc, 3, 3);
75 pixt = pixAnd(
nullptr, pixs, pixc);
77 pixCountConnComp(pixt, 8, &
count);
78 if (i == 1 ||
count > max_count) {
81 }
else if (i > 1 &&
count < min_count) {
84 pixout = pixCopy(
nullptr, pixt);
85 }
else if (
count >= min_count) {
102 int width = pixGetWidth(pix_binary_);
103 int height = pixGetHeight(pix_binary_);
105 auto pageseg_mode = static_cast<PageSegMode>(
109 input_file !=
nullptr && input_file->
length() > 0) {
110 STRING name = *input_file;
111 const char* lastdot = strrchr(name.
c_str(),
'.');
112 if (lastdot !=
nullptr)
113 name[lastdot - name.
c_str()] =
'\0';
116 if (blocks->empty()) {
119 BLOCK_IT block_it(blocks);
120 auto* block =
new BLOCK(
"",
true, 0, 0, 0, 0, width, height);
122 block_it.add_to_end(block);
133 BLOBNBOX_LIST diacritic_blobs;
134 int auto_page_seg_ret_val = 0;
135 TO_BLOCK_LIST to_blocks;
139 pageseg_mode, blocks, &to_blocks,
142 return auto_page_seg_ret_val;
146 deskew_ =
FCOORD(1.0f, 0.0f);
147 reskew_ =
FCOORD(1.0f, 0.0f);
149 Pix* pixcleaned = RemoveEnclosingCircle(pix_binary_);
150 if (pixcleaned !=
nullptr) {
151 pixDestroy(&pix_binary_);
152 pix_binary_ = pixcleaned;
157 if (auto_page_seg_ret_val < 0) {
161 if (blocks->empty()) {
170 textord_.
TextordPage(pageseg_mode, reskew_, width, height, pix_binary_,
171 pix_thresholds_, pix_grey_, splitting || cjk_mode,
172 &diacritic_blobs, blocks, &to_blocks);
173 return auto_page_seg_ret_val;
201 TO_BLOCK_LIST* to_blocks,
202 BLOBNBOX_LIST* diacritic_blobs, Tesseract* osd_tess,
204 Pix* photomask_pix =
nullptr;
205 Pix* musicmask_pix =
nullptr;
207 BLOCK_LIST found_blocks;
208 TO_BLOCK_LIST temp_blocks;
211 pageseg_mode, blocks, osd_tess, osr, &temp_blocks, &photomask_pix,
214 if (finder !=
nullptr) {
215 TO_BLOCK_IT to_block_it(&temp_blocks);
216 TO_BLOCK* to_block = to_block_it.data();
217 if (musicmask_pix !=
nullptr) {
220 pixOr(photomask_pix, photomask_pix, musicmask_pix);
223 finder->SetEquationDetect(equ_detect_);
225 result = finder->FindBlocks(pageseg_mode, scaled_color_, scaled_factor_,
226 to_block, photomask_pix, pix_thresholds_,
227 pix_grey_, &pixa_debug_, &found_blocks,
228 diacritic_blobs, to_blocks);
230 finder->GetDeskewVectors(&deskew_, &reskew_);
233 pixDestroy(&photomask_pix);
234 pixDestroy(&musicmask_pix);
235 if (result < 0)
return result;
238 BLOCK_IT block_it(blocks);
240 block_it.add_list_after(&found_blocks);
246 static void AddAllScriptsConverted(
const UNICHARSET& sid_set,
271 PageSegMode pageseg_mode, BLOCK_LIST* blocks, Tesseract* osd_tess,
272 OSResults* osr, TO_BLOCK_LIST* to_blocks, Pix** photo_mask_pix,
273 Pix** music_mask_pix) {
276 TabVector_LIST v_lines;
277 TabVector_LIST h_lines;
282 pixa_debug_.
AddPix(pix_binary_,
"PageSegInput");
287 &vertical_x, &vertical_y, music_mask_pix,
290 pixa_debug_.
AddPix(pix_binary_,
"NoLines");
295 pixa_debug_.
AddPix(pix_binary_,
"NoImages");
302 TO_BLOCK_IT to_block_it(to_blocks);
306 TO_BLOCK* to_block = to_block_it.data();
307 TBOX blkbox = to_block->block->pdblk.bounding_box();
308 ColumnFinder* finder =
nullptr;
309 int estimated_resolution = source_resolution_;
314 estimated_resolution = res;
315 tprintf(
"Estimating resolution as %d\n", estimated_resolution);
319 if (to_block->line_size >= 2) {
320 finder =
new ColumnFinder(static_cast<int>(to_block->line_size),
324 &h_lines, vertical_x, vertical_y);
326 finder->SetupAndFilterNoise(pageseg_mode, *photo_mask_pix, to_block);
328 #ifndef DISABLED_LEGACY_ENGINE
334 BLOBNBOX_CLIST osd_blobs;
339 int osd_orientation = 0;
346 to_block, &osd_blobs);
348 if (
PSM_OSD_ENABLED(pageseg_mode) && osd_tess !=
nullptr && osr !=
nullptr) {
350 if (osd_tess !=
this) {
353 AddAllScriptsConverted(
unicharset, osd_tess->unicharset, &osd_scripts);
354 for (
int s = 0; s < sub_langs_.size(); ++s) {
355 AddAllScriptsConverted(sub_langs_[s]->
unicharset,
356 osd_tess->unicharset, &osd_scripts);
367 for (
int i = 0; i < 4; ++i) {
368 if (i != osd_orientation &&
374 const char* best_script_str =
375 osd_tess->unicharset.get_script_from_script_id(best_script_id);
376 bool cjk = best_script_id == osd_tess->unicharset.han_sid() ||
377 best_script_id == osd_tess->unicharset.hiragana_sid() ||
378 best_script_id == osd_tess->unicharset.katakana_sid() ||
379 strcmp(
"Japanese", best_script_str) == 0 ||
380 strcmp(
"Korean", best_script_str) == 0 ||
381 strcmp(
"Hangul", best_script_str) == 0;
383 finder->set_cjk_script(
true);
387 if (!cjk && !vertical_text && osd_orientation == 2) {
389 tprintf(
"OSD: Weak margin (%.2f), horiz textlines, not CJK: "
390 "Don't rotate.\n", osd_margin);
394 "OSD: Weak margin (%.2f) for %d blob text block, "
395 "but using orientation anyway: %d\n",
396 osd_margin, osd_blobs.length(), osd_orientation);
400 osd_blobs.shallow_clear();
401 finder->CorrectOrientation(to_block, vertical_text, osd_orientation);
403 #endif // ndef DISABLED_LEGACY_ENGINE