tesseract  5.0.0
tesseract::ImageFind Class Reference

#include <imagefind.h>

Static Public Member Functions

static Image FindImages (Image pix, DebugPixa *pixa_debug)
 
static void ConnCompAndRectangularize (Image pix, DebugPixa *pixa_debug, Boxa **boxa, Pixa **pixa)
 
static bool pixNearlyRectangular (Image pix, double min_fraction, double max_fraction, double max_skew_gradient, int *x_start, int *y_start, int *x_end, int *y_end)
 
static bool BoundsWithinRect (Image pix, int *x_start, int *y_start, int *x_end, int *y_end)
 
static double ColorDistanceFromLine (const uint8_t *line1, const uint8_t *line2, const uint8_t *point)
 
static uint32_t ComposeRGB (uint32_t r, uint32_t g, uint32_t b)
 
static uint8_t ClipToByte (double pixel)
 
static void ComputeRectangleColors (const TBOX &rect, Image pix, int factor, Image color_map1, Image color_map2, Image rms_map, uint8_t *color1, uint8_t *color2)
 
static bool BlankImageInBetween (const TBOX &box1, const TBOX &box2, const TBOX &im_box, const FCOORD &rotation, Image pix)
 
static int CountPixelsInRotatedBox (TBOX box, const TBOX &im_box, const FCOORD &rotation, Image pix)
 
static void TransferImagePartsToImageMask (const FCOORD &rerotation, ColPartitionGrid *part_grid, Image image_mask)
 
static void FindImagePartitions (Image image_pix, const FCOORD &rotation, const FCOORD &rerotation, TO_BLOCK *block, TabFind *tab_grid, DebugPixa *pixa_debug, ColPartitionGrid *part_grid, ColPartition_LIST *big_parts)
 

Detailed Description

Definition at line 43 of file imagefind.h.

Member Function Documentation

◆ BlankImageInBetween()

bool tesseract::ImageFind::BlankImageInBetween ( const TBOX box1,
const TBOX box2,
const TBOX im_box,
const FCOORD rotation,
Image  pix 
)
static

Definition at line 587 of file imagefind.cpp.

588  {
589  TBOX search_box(box1);
590  search_box += box2;
591  if (box1.x_gap(box2) >= box1.y_gap(box2)) {
592  if (box1.x_gap(box2) <= 0) {
593  return true;
594  }
595  search_box.set_left(std::min(box1.right(), box2.right()));
596  search_box.set_right(std::max(box1.left(), box2.left()));
597  } else {
598  if (box1.y_gap(box2) <= 0) {
599  return true;
600  }
601  search_box.set_top(std::max(box1.bottom(), box2.bottom()));
602  search_box.set_bottom(std::min(box1.top(), box2.top()));
603  }
604  return CountPixelsInRotatedBox(search_box, im_box, rotation, pix) == 0;
605 }
@ TBOX
static int CountPixelsInRotatedBox(TBOX box, const TBOX &im_box, const FCOORD &rotation, Image pix)
Definition: imagefind.cpp:609

◆ BoundsWithinRect()

bool tesseract::ImageFind::BoundsWithinRect ( Image  pix,
int *  x_start,
int *  y_start,
int *  x_end,
int *  y_end 
)
static

Definition at line 351 of file imagefind.cpp.

351  {
352  Box *input_box = boxCreate(*x_start, *y_start, *x_end - *x_start, *y_end - *y_start);
353  Box *output_box = nullptr;
354  pixClipBoxToForeground(pix, input_box, nullptr, &output_box);
355  bool result = output_box != nullptr;
356  if (result) {
357  l_int32 x, y, width, height;
358  boxGetGeometry(output_box, &x, &y, &width, &height);
359  *x_start = x;
360  *y_start = y;
361  *x_end = x + width;
362  *y_end = y + height;
363  boxDestroy(&output_box);
364  }
365  boxDestroy(&input_box);
366  return result;
367 }

◆ ClipToByte()

uint8_t tesseract::ImageFind::ClipToByte ( double  pixel)
static

Definition at line 411 of file imagefind.cpp.

411  {
412  if (pixel < 0.0) {
413  return 0;
414  } else if (pixel >= 255.0) {
415  return 255;
416  }
417  return static_cast<uint8_t>(pixel);
418 }

◆ ColorDistanceFromLine()

double tesseract::ImageFind::ColorDistanceFromLine ( const uint8_t *  line1,
const uint8_t *  line2,
const uint8_t *  point 
)
static

Definition at line 372 of file imagefind.cpp.

373  {
374  int line_vector[kRGBRMSColors];
375  int point_vector[kRGBRMSColors];
376  for (int i = 0; i < kRGBRMSColors; ++i) {
377  line_vector[i] = static_cast<int>(line2[i]) - static_cast<int>(line1[i]);
378  point_vector[i] = static_cast<int>(point[i]) - static_cast<int>(line1[i]);
379  }
380  line_vector[L_ALPHA_CHANNEL] = 0;
381  // Now the cross product in 3d.
382  int cross[kRGBRMSColors];
383  cross[COLOR_RED] = line_vector[COLOR_GREEN] * point_vector[COLOR_BLUE] -
384  line_vector[COLOR_BLUE] * point_vector[COLOR_GREEN];
385  cross[COLOR_GREEN] = line_vector[COLOR_BLUE] * point_vector[COLOR_RED] -
386  line_vector[COLOR_RED] * point_vector[COLOR_BLUE];
387  cross[COLOR_BLUE] = line_vector[COLOR_RED] * point_vector[COLOR_GREEN] -
388  line_vector[COLOR_GREEN] * point_vector[COLOR_RED];
389  cross[L_ALPHA_CHANNEL] = 0;
390  // Now the sums of the squares.
391  double cross_sq = 0.0;
392  double line_sq = 0.0;
393  for (int j = 0; j < kRGBRMSColors; ++j) {
394  cross_sq += static_cast<double>(cross[j]) * cross[j];
395  line_sq += static_cast<double>(line_vector[j]) * line_vector[j];
396  }
397  if (line_sq == 0.0) {
398  return 0.0;
399  }
400  return cross_sq / line_sq; // This is the squared distance.
401 }
const int kRGBRMSColors
Definition: colpartition.h:36

◆ ComposeRGB()

uint32_t tesseract::ImageFind::ComposeRGB ( uint32_t  r,
uint32_t  g,
uint32_t  b 
)
static

Definition at line 404 of file imagefind.cpp.

404  {
405  l_uint32 result;
406  composeRGBPixel(r, g, b, &result);
407  return result;
408 }

◆ ComputeRectangleColors()

void tesseract::ImageFind::ComputeRectangleColors ( const TBOX rect,
Image  pix,
int  factor,
Image  color_map1,
Image  color_map2,
Image  rms_map,
uint8_t *  color1,
uint8_t *  color2 
)
static

Definition at line 430 of file imagefind.cpp.

432  {
433  ASSERT_HOST(pix != nullptr && pixGetDepth(pix) == 32);
434  // Pad the rectangle outwards by 2 (scaled) pixels if possible to get more
435  // background.
436  int width = pixGetWidth(pix);
437  int height = pixGetHeight(pix);
438  int left_pad = std::max(rect.left() - 2 * factor, 0) / factor;
439  int top_pad = (rect.top() + 2 * factor + (factor - 1)) / factor;
440  top_pad = std::min(height, top_pad);
441  int right_pad = (rect.right() + 2 * factor + (factor - 1)) / factor;
442  right_pad = std::min(width, right_pad);
443  int bottom_pad = std::max(rect.bottom() - 2 * factor, 0) / factor;
444  int width_pad = right_pad - left_pad;
445  int height_pad = top_pad - bottom_pad;
446  if (width_pad < 1 || height_pad < 1 || width_pad + height_pad < 4) {
447  return;
448  }
449  // Now crop the pix to the rectangle.
450  Box *scaled_box = boxCreate(left_pad, height - top_pad, width_pad, height_pad);
451  Image scaled = pixClipRectangle(pix, scaled_box, nullptr);
452 
453  // Compute stats over the whole image.
454  STATS red_stats(0, 256);
455  STATS green_stats(0, 256);
456  STATS blue_stats(0, 256);
457  uint32_t *data = pixGetData(scaled);
458  ASSERT_HOST(pixGetWpl(scaled) == width_pad);
459  for (int y = 0; y < height_pad; ++y) {
460  for (int x = 0; x < width_pad; ++x, ++data) {
461  int r = GET_DATA_BYTE(data, COLOR_RED);
462  int g = GET_DATA_BYTE(data, COLOR_GREEN);
463  int b = GET_DATA_BYTE(data, COLOR_BLUE);
464  red_stats.add(r, 1);
465  green_stats.add(g, 1);
466  blue_stats.add(b, 1);
467  }
468  }
469  // Find the RGB component with the greatest 8th-ile-range.
470  // 8th-iles are used instead of quartiles to get closer to the true
471  // foreground color, which is going to be faint at best because of the
472  // pre-scaling of the input image.
473  int best_l8 = static_cast<int>(red_stats.ile(0.125f));
474  int best_u8 = static_cast<int>(ceil(red_stats.ile(0.875f)));
475  int best_i8r = best_u8 - best_l8;
476  int x_color = COLOR_RED;
477  int y1_color = COLOR_GREEN;
478  int y2_color = COLOR_BLUE;
479  int l8 = static_cast<int>(green_stats.ile(0.125f));
480  int u8 = static_cast<int>(ceil(green_stats.ile(0.875f)));
481  if (u8 - l8 > best_i8r) {
482  best_i8r = u8 - l8;
483  best_l8 = l8;
484  best_u8 = u8;
485  x_color = COLOR_GREEN;
486  y1_color = COLOR_RED;
487  }
488  l8 = static_cast<int>(blue_stats.ile(0.125f));
489  u8 = static_cast<int>(ceil(blue_stats.ile(0.875f)));
490  if (u8 - l8 > best_i8r) {
491  best_i8r = u8 - l8;
492  best_l8 = l8;
493  best_u8 = u8;
494  x_color = COLOR_BLUE;
495  y1_color = COLOR_GREEN;
496  y2_color = COLOR_RED;
497  }
498  if (best_i8r >= kMinColorDifference) {
499  LLSQ line1;
500  LLSQ line2;
501  uint32_t *data = pixGetData(scaled);
502  for (int im_y = 0; im_y < height_pad; ++im_y) {
503  for (int im_x = 0; im_x < width_pad; ++im_x, ++data) {
504  int x = GET_DATA_BYTE(data, x_color);
505  int y1 = GET_DATA_BYTE(data, y1_color);
506  int y2 = GET_DATA_BYTE(data, y2_color);
507  line1.add(x, y1);
508  line2.add(x, y2);
509  }
510  }
511  double m1 = line1.m();
512  double c1 = line1.c(m1);
513  double m2 = line2.m();
514  double c2 = line2.c(m2);
515  double rms = line1.rms(m1, c1) + line2.rms(m2, c2);
516  rms *= kRMSFitScaling;
517  // Save the results.
518  color1[x_color] = ClipToByte(best_l8);
519  color1[y1_color] = ClipToByte(m1 * best_l8 + c1 + 0.5);
520  color1[y2_color] = ClipToByte(m2 * best_l8 + c2 + 0.5);
521  color1[L_ALPHA_CHANNEL] = ClipToByte(rms);
522  color2[x_color] = ClipToByte(best_u8);
523  color2[y1_color] = ClipToByte(m1 * best_u8 + c1 + 0.5);
524  color2[y2_color] = ClipToByte(m2 * best_u8 + c2 + 0.5);
525  color2[L_ALPHA_CHANNEL] = ClipToByte(rms);
526  } else {
527  // There is only one color.
528  color1[COLOR_RED] = ClipToByte(red_stats.median());
529  color1[COLOR_GREEN] = ClipToByte(green_stats.median());
530  color1[COLOR_BLUE] = ClipToByte(blue_stats.median());
531  color1[L_ALPHA_CHANNEL] = 0;
532  memcpy(color2, color1, 4);
533  }
534  if (color_map1 != nullptr) {
535  pixSetInRectArbitrary(color_map1, scaled_box,
536  ComposeRGB(color1[COLOR_RED], color1[COLOR_GREEN], color1[COLOR_BLUE]));
537  pixSetInRectArbitrary(color_map2, scaled_box,
538  ComposeRGB(color2[COLOR_RED], color2[COLOR_GREEN], color2[COLOR_BLUE]));
539  pixSetInRectArbitrary(rms_map, scaled_box, color1[L_ALPHA_CHANNEL]);
540  }
541  scaled.destroy();
542  boxDestroy(&scaled_box);
543 }
#define ASSERT_HOST(x)
Definition: errcode.h:59
const double kRMSFitScaling
Definition: imagefind.cpp:50
const int kMinColorDifference
Definition: imagefind.cpp:52
static uint32_t ComposeRGB(uint32_t r, uint32_t g, uint32_t b)
Definition: imagefind.cpp:404
static uint8_t ClipToByte(double pixel)
Definition: imagefind.cpp:411

◆ ConnCompAndRectangularize()

void tesseract::ImageFind::ConnCompAndRectangularize ( Image  pix,
DebugPixa pixa_debug,
Boxa **  boxa,
Pixa **  pixa 
)
static

Definition at line 161 of file imagefind.cpp.

162  {
163  *boxa = nullptr;
164  *pixa = nullptr;
165 
166  if (textord_tabfind_show_images && pixa_debug != nullptr) {
167  pixa_debug->AddPix(pix, "Conncompimage");
168  }
169  // Find the individual image regions in the mask image.
170  *boxa = pixConnComp(pix, pixa, 8);
171  // Rectangularize the individual images. If a sharp edge in vertical and/or
172  // horizontal occupancy can be found, it indicates a probably rectangular
173  // image with unwanted bits merged on, so clip to the approximate rectangle.
174  int npixes = 0;
175  if (*boxa != nullptr && *pixa != nullptr) {
176  npixes = pixaGetCount(*pixa);
177  }
178  for (int i = 0; i < npixes; ++i) {
179  int x_start, x_end, y_start, y_end;
180  Image img_pix = pixaGetPix(*pixa, i, L_CLONE);
181  if (textord_tabfind_show_images && pixa_debug != nullptr) {
182  pixa_debug->AddPix(img_pix, "A component");
183  }
185  kMaxRectangularGradient, &x_start, &y_start, &x_end, &y_end)) {
186  Image simple_pix = pixCreate(x_end - x_start, y_end - y_start, 1);
187  pixSetAll(simple_pix);
188  img_pix.destroy();
189  // pixaReplacePix takes ownership of the simple_pix.
190  pixaReplacePix(*pixa, i, simple_pix, nullptr);
191  img_pix = pixaGetPix(*pixa, i, L_CLONE);
192  // Fix the box to match the new pix.
193  l_int32 x, y, width, height;
194  boxaGetBoxGeometry(*boxa, i, &x, &y, &width, &height);
195  Box *simple_box = boxCreate(x + x_start, y + y_start, x_end - x_start, y_end - y_start);
196  boxaReplaceBox(*boxa, i, simple_box);
197  }
198  img_pix.destroy();
199  }
200 }
const double kMinRectangularFraction
Definition: imagefind.cpp:41
const double kMaxRectangularGradient
Definition: imagefind.cpp:46
const double kMaxRectangularFraction
Definition: imagefind.cpp:43
static bool pixNearlyRectangular(Image pix, double min_fraction, double max_fraction, double max_skew_gradient, int *x_start, int *y_start, int *x_end, int *y_end)
Definition: imagefind.cpp:283

◆ CountPixelsInRotatedBox()

int tesseract::ImageFind::CountPixelsInRotatedBox ( TBOX  box,
const TBOX im_box,
const FCOORD rotation,
Image  pix 
)
static

Definition at line 609 of file imagefind.cpp.

610  {
611  // Intersect it with the image box.
612  box &= im_box; // This is in-place box intersection.
613  if (box.null_box()) {
614  return 0;
615  }
616  box.rotate(rotation);
617  TBOX rotated_im_box(im_box);
618  rotated_im_box.rotate(rotation);
619  Image rect_pix = pixCreate(box.width(), box.height(), 1);
620  pixRasterop(rect_pix, 0, 0, box.width(), box.height(), PIX_SRC, pix,
621  box.left() - rotated_im_box.left(), rotated_im_box.top() - box.top());
622  l_int32 result;
623  pixCountPixels(rect_pix, &result, nullptr);
624  rect_pix.destroy();
625  return result;
626 }

◆ FindImagePartitions()

void tesseract::ImageFind::FindImagePartitions ( Image  image_pix,
const FCOORD rotation,
const FCOORD rerotation,
TO_BLOCK block,
TabFind tab_grid,
DebugPixa pixa_debug,
ColPartitionGrid part_grid,
ColPartition_LIST *  big_parts 
)
static

Definition at line 1291 of file imagefind.cpp.

1294  {
1295  int imageheight = pixGetHeight(image_pix);
1296  Boxa *boxa;
1297  Pixa *pixa;
1298  ConnCompAndRectangularize(image_pix, pixa_debug, &boxa, &pixa);
1299  // Iterate the connected components in the image regions mask.
1300  int nboxes = 0;
1301  if (boxa != nullptr && pixa != nullptr) {
1302  nboxes = boxaGetCount(boxa);
1303  }
1304  for (int i = 0; i < nboxes; ++i) {
1305  l_int32 x, y, width, height;
1306  boxaGetBoxGeometry(boxa, i, &x, &y, &width, &height);
1307  Image pix = pixaGetPix(pixa, i, L_CLONE);
1308  TBOX im_box(x, imageheight - y - height, x + width, imageheight - y);
1309  im_box.rotate(rotation); // Now matches all partitions and blobs.
1310  ColPartitionGridSearch rectsearch(part_grid);
1311  rectsearch.SetUniqueMode(true);
1312  ColPartition_LIST part_list;
1313  DivideImageIntoParts(im_box, rotation, rerotation, pix, &rectsearch, &part_list);
1314  if (textord_tabfind_show_images && pixa_debug != nullptr) {
1315  pixa_debug->AddPix(pix, "ImageComponent");
1316  tprintf("Component has %d parts\n", part_list.length());
1317  }
1318  pix.destroy();
1319  if (!part_list.empty()) {
1320  ColPartition_IT part_it(&part_list);
1321  if (part_list.singleton()) {
1322  // We didn't have to chop it into a polygon to fit around text, so
1323  // try expanding it to merge fragmented image parts, as long as it
1324  // doesn't touch strong text.
1325  ColPartition *part = part_it.extract();
1326  TBOX text_box(im_box);
1327  MaximalImageBoundingBox(part_grid, &text_box);
1328  while (ExpandImageIntoParts(text_box, &rectsearch, part_grid, &part)) {
1329  ;
1330  }
1331  part_it.set_to_list(&part_list);
1332  part_it.add_after_then_move(part);
1333  im_box = part->bounding_box();
1334  }
1335  EliminateWeakParts(im_box, part_grid, big_parts, &part_list);
1336  // Iterate the part_list and put the parts into the grid.
1337  for (part_it.move_to_first(); !part_it.empty(); part_it.forward()) {
1338  ColPartition *image_part = part_it.extract();
1339  im_box = image_part->bounding_box();
1340  part_grid->InsertBBox(true, true, image_part);
1341  if (!part_it.at_last()) {
1342  ColPartition *neighbour = part_it.data_relative(1);
1343  image_part->AddPartner(false, neighbour);
1344  neighbour->AddPartner(true, image_part);
1345  }
1346  }
1347  }
1348  }
1349  boxaDestroy(&boxa);
1350  pixaDestroy(&pixa);
1351  DeleteSmallImages(part_grid);
1352 #ifndef GRAPHICS_DISABLED
1353  if (textord_tabfind_show_images) {
1354  ScrollView *images_win_ = part_grid->MakeWindow(1000, 400, "With Images");
1355  part_grid->DisplayBoxes(images_win_);
1356  }
1357 #endif
1358 }
void tprintf(const char *format,...)
Definition: tprintf.cpp:41
GridSearch< ColPartition, ColPartition_CLIST, ColPartition_C_IT > ColPartitionGridSearch
Definition: colpartition.h:919
static void ConnCompAndRectangularize(Image pix, DebugPixa *pixa_debug, Boxa **boxa, Pixa **pixa)
Definition: imagefind.cpp:161

◆ FindImages()

Image tesseract::ImageFind::FindImages ( Image  pix,
DebugPixa pixa_debug 
)
static

Definition at line 63 of file imagefind.cpp.

63  {
64  // Not worth looking at small images.
65  if (pixGetWidth(pix) < kMinImageFindSize || pixGetHeight(pix) < kMinImageFindSize) {
66  return pixCreate(pixGetWidth(pix), pixGetHeight(pix), 1);
67  }
68 
69  // Reduce by factor 2.
70  Image pixr = pixReduceRankBinaryCascade(pix, 1, 0, 0, 0);
71  if (textord_tabfind_show_images && pixa_debug != nullptr) {
72  pixa_debug->AddPix(pixr, "CascadeReduced");
73  }
74 
75  // Get the halftone mask directly from Leptonica.
76  //
77  // Leptonica will print an error message and return nullptr if we call
78  // pixGenHalftoneMask(pixr, nullptr, ...) with too small image, so we
79  // want to bypass that.
80  if (pixGetWidth(pixr) < kMinImageFindSize || pixGetHeight(pixr) < kMinImageFindSize) {
81  pixr.destroy();
82  return pixCreate(pixGetWidth(pix), pixGetHeight(pix), 1);
83  }
84  // Get the halftone mask.
85  l_int32 ht_found = 0;
86  Pixa *pixadb = (textord_tabfind_show_images && pixa_debug != nullptr) ? pixaCreate(0) : nullptr;
87  Image pixht2 = pixGenerateHalftoneMask(pixr, nullptr, &ht_found, pixadb);
88  if (pixadb) {
89  Image pixdb = pixaDisplayTiledInColumns(pixadb, 3, 1.0, 20, 2);
90  if (textord_tabfind_show_images && pixa_debug != nullptr) {
91  pixa_debug->AddPix(pixdb, "HalftoneMask");
92  }
93  pixdb.destroy();
94  pixaDestroy(&pixadb);
95  }
96  pixr.destroy();
97  if (!ht_found && pixht2 != nullptr) {
98  pixht2.destroy();
99  }
100  if (pixht2 == nullptr) {
101  return pixCreate(pixGetWidth(pix), pixGetHeight(pix), 1);
102  }
103 
104  // Expand back up again.
105  Image pixht = pixExpandReplicate(pixht2, 2);
106  if (textord_tabfind_show_images && pixa_debug != nullptr) {
107  pixa_debug->AddPix(pixht, "HalftoneReplicated");
108  }
109  pixht2.destroy();
110 
111  // Fill to capture pixels near the mask edges that were missed
112  Image pixt = pixSeedfillBinary(nullptr, pixht, pix, 8);
113  pixht |= pixt;
114  pixt.destroy();
115 
116  // Eliminate lines and bars that may be joined to images.
117  Image pixfinemask = pixReduceRankBinaryCascade(pixht, 1, 1, 3, 3);
118  pixDilateBrick(pixfinemask, pixfinemask, 5, 5);
119  if (textord_tabfind_show_images && pixa_debug != nullptr) {
120  pixa_debug->AddPix(pixfinemask, "FineMask");
121  }
122  Image pixreduced = pixReduceRankBinaryCascade(pixht, 1, 1, 1, 1);
123  Image pixreduced2 = pixReduceRankBinaryCascade(pixreduced, 3, 3, 3, 0);
124  pixreduced.destroy();
125  pixDilateBrick(pixreduced2, pixreduced2, 5, 5);
126  Image pixcoarsemask = pixExpandReplicate(pixreduced2, 8);
127  pixreduced2.destroy();
128  if (textord_tabfind_show_images && pixa_debug != nullptr) {
129  pixa_debug->AddPix(pixcoarsemask, "CoarseMask");
130  }
131  // Combine the coarse and fine image masks.
132  pixcoarsemask &= pixfinemask;
133  pixfinemask.destroy();
134  // Dilate a bit to make sure we get everything.
135  pixDilateBrick(pixcoarsemask, pixcoarsemask, 3, 3);
136  Image pixmask = pixExpandReplicate(pixcoarsemask, 16);
137  pixcoarsemask.destroy();
138  if (textord_tabfind_show_images && pixa_debug != nullptr) {
139  pixa_debug->AddPix(pixmask, "MaskDilated");
140  }
141  // And the image mask with the line and bar remover.
142  pixht &= pixmask;
143  pixmask.destroy();
144  if (textord_tabfind_show_images && pixa_debug != nullptr) {
145  pixa_debug->AddPix(pixht, "FinalMask");
146  }
147  // Make the result image the same size as the input.
148  Image result = pixCreate(pixGetWidth(pix), pixGetHeight(pix), 1);
149  result |= pixht;
150  pixht.destroy();
151  return result;
152 }
const int kMinImageFindSize
Definition: imagefind.cpp:48

◆ pixNearlyRectangular()

bool tesseract::ImageFind::pixNearlyRectangular ( Image  pix,
double  min_fraction,
double  max_fraction,
double  max_skew_gradient,
int *  x_start,
int *  y_start,
int *  x_end,
int *  y_end 
)
static

Definition at line 283 of file imagefind.cpp.

285  {
286  ASSERT_HOST(pix != nullptr);
287  *x_start = 0;
288  *x_end = pixGetWidth(pix);
289  *y_start = 0;
290  *y_end = pixGetHeight(pix);
291 
292  uint32_t *data = pixGetData(pix);
293  int wpl = pixGetWpl(pix);
294  bool any_cut = false;
295  bool left_done = false;
296  bool right_done = false;
297  bool top_done = false;
298  bool bottom_done = false;
299  do {
300  any_cut = false;
301  // Find the top/bottom edges.
302  int width = *x_end - *x_start;
303  int min_count = static_cast<int>(width * min_fraction);
304  int max_count = static_cast<int>(width * max_fraction);
305  int edge_width = static_cast<int>(width * max_skew_gradient);
306  if (HScanForEdge(data, wpl, *x_start, *x_end, min_count, edge_width, max_count, *y_end, 1,
307  y_start) &&
308  !top_done) {
309  top_done = true;
310  any_cut = true;
311  }
312  --(*y_end);
313  if (HScanForEdge(data, wpl, *x_start, *x_end, min_count, edge_width, max_count, *y_start, -1,
314  y_end) &&
315  !bottom_done) {
316  bottom_done = true;
317  any_cut = true;
318  }
319  ++(*y_end);
320 
321  // Find the left/right edges.
322  int height = *y_end - *y_start;
323  min_count = static_cast<int>(height * min_fraction);
324  max_count = static_cast<int>(height * max_fraction);
325  edge_width = static_cast<int>(height * max_skew_gradient);
326  if (VScanForEdge(data, wpl, *y_start, *y_end, min_count, edge_width, max_count, *x_end, 1,
327  x_start) &&
328  !left_done) {
329  left_done = true;
330  any_cut = true;
331  }
332  --(*x_end);
333  if (VScanForEdge(data, wpl, *y_start, *y_end, min_count, edge_width, max_count, *x_start, -1,
334  x_end) &&
335  !right_done) {
336  right_done = true;
337  any_cut = true;
338  }
339  ++(*x_end);
340  } while (any_cut);
341 
342  // All edges must satisfy the condition of sharp gradient in pixel density
343  // in order for the full rectangle to be present.
344  return left_done && right_done && top_done && bottom_done;
345 }

◆ TransferImagePartsToImageMask()

void tesseract::ImageFind::TransferImagePartsToImageMask ( const FCOORD rerotation,
ColPartitionGrid part_grid,
Image  image_mask 
)
static

Definition at line 1238 of file imagefind.cpp.

1239  {
1240  // Extract the noise parts from the grid and put them on a temporary list.
1241  ColPartition_LIST parts_list;
1242  ColPartition_IT part_it(&parts_list);
1243  ColPartitionGridSearch gsearch(part_grid);
1244  gsearch.StartFullSearch();
1245  ColPartition *part;
1246  while ((part = gsearch.NextFullSearch()) != nullptr) {
1247  BlobRegionType type = part->blob_type();
1248  if (type == BRT_NOISE || type == BRT_RECTIMAGE || type == BRT_POLYIMAGE) {
1249  part_it.add_after_then_move(part);
1250  gsearch.RemoveBBox();
1251  }
1252  }
1253  // Render listed noise partitions to the image mask.
1254  MarkAndDeleteImageParts(rerotation, part_grid, &parts_list, image_mask);
1255 }
BlobRegionType
Definition: blobbox.h:74
@ BRT_NOISE
Definition: blobbox.h:75
@ BRT_POLYIMAGE
Definition: blobbox.h:79
@ BRT_RECTIMAGE
Definition: blobbox.h:78

The documentation for this class was generated from the following files: