tesseract  3.05.02
tesseract::ImageFind Class Reference

#include <imagefind.h>

Static Public Member Functions

static Pix * FindImages (Pix *pix)
 
static void ConnCompAndRectangularize (Pix *pix, Boxa **boxa, Pixa **pixa)
 
static bool pixNearlyRectangular (Pix *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 (Pix *pix, int *x_start, int *y_start, int *x_end, int *y_end)
 
static double ColorDistanceFromLine (const uinT8 *line1, const uinT8 *line2, const uinT8 *point)
 
static uinT32 ComposeRGB (uinT32 r, uinT32 g, uinT32 b)
 
static uinT8 ClipToByte (double pixel)
 
static void ComputeRectangleColors (const TBOX &rect, Pix *pix, int factor, Pix *color_map1, Pix *color_map2, Pix *rms_map, uinT8 *color1, uinT8 *color2)
 
static bool BlankImageInBetween (const TBOX &box1, const TBOX &box2, const TBOX &im_box, const FCOORD &rotation, Pix *pix)
 
static int CountPixelsInRotatedBox (TBOX box, const TBOX &im_box, const FCOORD &rotation, Pix *pix)
 
static void TransferImagePartsToImageMask (const FCOORD &rerotation, ColPartitionGrid *part_grid, Pix *image_mask)
 
static void FindImagePartitions (Pix *image_pix, const FCOORD &rotation, const FCOORD &rerotation, TO_BLOCK *block, TabFind *tab_grid, ColPartitionGrid *part_grid, ColPartition_LIST *big_parts)
 

Detailed Description

Definition at line 42 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,
Pix *  pix 
)
static

Definition at line 562 of file imagefind.cpp.

564  {
565  TBOX search_box(box1);
566  search_box += box2;
567  if (box1.x_gap(box2) >= box1.y_gap(box2)) {
568  if (box1.x_gap(box2) <= 0)
569  return true;
570  search_box.set_left(MIN(box1.right(), box2.right()));
571  search_box.set_right(MAX(box1.left(), box2.left()));
572  } else {
573  if (box1.y_gap(box2) <= 0)
574  return true;
575  search_box.set_top(MAX(box1.bottom(), box2.bottom()));
576  search_box.set_bottom(MIN(box1.top(), box2.top()));
577  }
578  return CountPixelsInRotatedBox(search_box, im_box, rotation, pix) == 0;
579 }
static int CountPixelsInRotatedBox(TBOX box, const TBOX &im_box, const FCOORD &rotation, Pix *pix)
Definition: imagefind.cpp:583
#define MIN(x, y)
Definition: ndminx.h:28
void set_left(int x)
Definition: rect.h:71
int y_gap(const TBOX &box) const
Definition: rect.h:225
inT16 bottom() const
Definition: rect.h:61
inT16 left() const
Definition: rect.h:68
int x_gap(const TBOX &box) const
Definition: rect.h:217
#define MAX(x, y)
Definition: ndminx.h:24
inT16 top() const
Definition: rect.h:54
Definition: rect.h:30
inT16 right() const
Definition: rect.h:75

◆ BoundsWithinRect()

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

Definition at line 318 of file imagefind.cpp.

319  {
320  Box* input_box = boxCreate(*x_start, *y_start, *x_end - *x_start,
321  *y_end - *y_start);
322  Box* output_box = NULL;
323  pixClipBoxToForeground(pix, input_box, NULL, &output_box);
324  bool result = output_box != NULL;
325  if (result) {
326  l_int32 x, y, width, height;
327  boxGetGeometry(output_box, &x, &y, &width, &height);
328  *x_start = x;
329  *y_start = y;
330  *x_end = x + width;
331  *y_end = y + height;
332  boxDestroy(&output_box);
333  }
334  boxDestroy(&input_box);
335  return result;
336 }

◆ ClipToByte()

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

Definition at line 382 of file imagefind.cpp.

382  {
383  if (pixel < 0.0)
384  return 0;
385  else if (pixel >= 255.0)
386  return 255;
387  return static_cast<uinT8>(pixel);
388 }
unsigned char uinT8
Definition: host.h:32

◆ ColorDistanceFromLine()

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

Definition at line 341 of file imagefind.cpp.

343  {
344  int line_vector[kRGBRMSColors];
345  int point_vector[kRGBRMSColors];
346  for (int i = 0; i < kRGBRMSColors; ++i) {
347  line_vector[i] = static_cast<int>(line2[i]) - static_cast<int>(line1[i]);
348  point_vector[i] = static_cast<int>(point[i]) - static_cast<int>(line1[i]);
349  }
350  line_vector[L_ALPHA_CHANNEL] = 0;
351  // Now the cross product in 3d.
352  int cross[kRGBRMSColors];
353  cross[COLOR_RED] = line_vector[COLOR_GREEN] * point_vector[COLOR_BLUE]
354  - line_vector[COLOR_BLUE] * point_vector[COLOR_GREEN];
355  cross[COLOR_GREEN] = line_vector[COLOR_BLUE] * point_vector[COLOR_RED]
356  - line_vector[COLOR_RED] * point_vector[COLOR_BLUE];
357  cross[COLOR_BLUE] = line_vector[COLOR_RED] * point_vector[COLOR_GREEN]
358  - line_vector[COLOR_GREEN] * point_vector[COLOR_RED];
359  cross[L_ALPHA_CHANNEL] = 0;
360  // Now the sums of the squares.
361  double cross_sq = 0.0;
362  double line_sq = 0.0;
363  for (int j = 0; j < kRGBRMSColors; ++j) {
364  cross_sq += static_cast<double>(cross[j]) * cross[j];
365  line_sq += static_cast<double>(line_vector[j]) * line_vector[j];
366  }
367  if (line_sq == 0.0) {
368  return 0.0;
369  }
370  return cross_sq / line_sq; // This is the squared distance.
371 }
const int kRGBRMSColors
Definition: colpartition.h:36

◆ ComposeRGB()

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

Definition at line 375 of file imagefind.cpp.

375  {
376  l_uint32 result;
377  composeRGBPixel(r, g, b, &result);
378  return result;
379 }

◆ ComputeRectangleColors()

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

Definition at line 400 of file imagefind.cpp.

403  {
404  ASSERT_HOST(pix != NULL && pixGetDepth(pix) == 32);
405  // Pad the rectangle outwards by 2 (scaled) pixels if possible to get more
406  // background.
407  int width = pixGetWidth(pix);
408  int height = pixGetHeight(pix);
409  int left_pad = MAX(rect.left() - 2 * factor, 0) / factor;
410  int top_pad = (rect.top() + 2 * factor + (factor - 1)) / factor;
411  top_pad = MIN(height, top_pad);
412  int right_pad = (rect.right() + 2 * factor + (factor - 1)) / factor;
413  right_pad = MIN(width, right_pad);
414  int bottom_pad = MAX(rect.bottom() - 2 * factor, 0) / factor;
415  int width_pad = right_pad - left_pad;
416  int height_pad = top_pad - bottom_pad;
417  if (width_pad < 1 || height_pad < 1 || width_pad + height_pad < 4)
418  return;
419  // Now crop the pix to the rectangle.
420  Box* scaled_box = boxCreate(left_pad, height - top_pad,
421  width_pad, height_pad);
422  Pix* scaled = pixClipRectangle(pix, scaled_box, NULL);
423 
424  // Compute stats over the whole image.
425  STATS red_stats(0, 256);
426  STATS green_stats(0, 256);
427  STATS blue_stats(0, 256);
428  uinT32* data = pixGetData(scaled);
429  ASSERT_HOST(pixGetWpl(scaled) == width_pad);
430  for (int y = 0; y < height_pad; ++y) {
431  for (int x = 0; x < width_pad; ++x, ++data) {
432  int r = GET_DATA_BYTE(data, COLOR_RED);
433  int g = GET_DATA_BYTE(data, COLOR_GREEN);
434  int b = GET_DATA_BYTE(data, COLOR_BLUE);
435  red_stats.add(r, 1);
436  green_stats.add(g, 1);
437  blue_stats.add(b, 1);
438  }
439  }
440  // Find the RGB component with the greatest 8th-ile-range.
441  // 8th-iles are used instead of quartiles to get closer to the true
442  // foreground color, which is going to be faint at best because of the
443  // pre-scaling of the input image.
444  int best_l8 = static_cast<int>(red_stats.ile(0.125f));
445  int best_u8 = static_cast<int>(ceil(red_stats.ile(0.875f)));
446  int best_i8r = best_u8 - best_l8;
447  int x_color = COLOR_RED;
448  int y1_color = COLOR_GREEN;
449  int y2_color = COLOR_BLUE;
450  int l8 = static_cast<int>(green_stats.ile(0.125f));
451  int u8 = static_cast<int>(ceil(green_stats.ile(0.875f)));
452  if (u8 - l8 > best_i8r) {
453  best_i8r = u8 - l8;
454  best_l8 = l8;
455  best_u8 = u8;
456  x_color = COLOR_GREEN;
457  y1_color = COLOR_RED;
458  }
459  l8 = static_cast<int>(blue_stats.ile(0.125f));
460  u8 = static_cast<int>(ceil(blue_stats.ile(0.875f)));
461  if (u8 - l8 > best_i8r) {
462  best_i8r = u8 - l8;
463  best_l8 = l8;
464  best_u8 = u8;
465  x_color = COLOR_BLUE;
466  y1_color = COLOR_GREEN;
467  y2_color = COLOR_RED;
468  }
469  if (best_i8r >= kMinColorDifference) {
470  LLSQ line1;
471  LLSQ line2;
472  uinT32* data = pixGetData(scaled);
473  for (int im_y = 0; im_y < height_pad; ++im_y) {
474  for (int im_x = 0; im_x < width_pad; ++im_x, ++data) {
475  int x = GET_DATA_BYTE(data, x_color);
476  int y1 = GET_DATA_BYTE(data, y1_color);
477  int y2 = GET_DATA_BYTE(data, y2_color);
478  line1.add(x, y1);
479  line2.add(x, y2);
480  }
481  }
482  double m1 = line1.m();
483  double c1 = line1.c(m1);
484  double m2 = line2.m();
485  double c2 = line2.c(m2);
486  double rms = line1.rms(m1, c1) + line2.rms(m2, c2);
487  rms *= kRMSFitScaling;
488  // Save the results.
489  color1[x_color] = ClipToByte(best_l8);
490  color1[y1_color] = ClipToByte(m1 * best_l8 + c1 + 0.5);
491  color1[y2_color] = ClipToByte(m2 * best_l8 + c2 + 0.5);
492  color1[L_ALPHA_CHANNEL] = ClipToByte(rms);
493  color2[x_color] = ClipToByte(best_u8);
494  color2[y1_color] = ClipToByte(m1 * best_u8 + c1 + 0.5);
495  color2[y2_color] = ClipToByte(m2 * best_u8 + c2 + 0.5);
496  color2[L_ALPHA_CHANNEL] = ClipToByte(rms);
497  } else {
498  // There is only one color.
499  color1[COLOR_RED] = ClipToByte(red_stats.median());
500  color1[COLOR_GREEN] = ClipToByte(green_stats.median());
501  color1[COLOR_BLUE] = ClipToByte(blue_stats.median());
502  color1[L_ALPHA_CHANNEL] = 0;
503  memcpy(color2, color1, 4);
504  }
505  if (color_map1 != NULL) {
506  pixSetInRectArbitrary(color_map1, scaled_box,
507  ComposeRGB(color1[COLOR_RED],
508  color1[COLOR_GREEN],
509  color1[COLOR_BLUE]));
510  pixSetInRectArbitrary(color_map2, scaled_box,
511  ComposeRGB(color2[COLOR_RED],
512  color2[COLOR_GREEN],
513  color2[COLOR_BLUE]));
514  pixSetInRectArbitrary(rms_map, scaled_box, color1[L_ALPHA_CHANNEL]);
515  }
516  pixDestroy(&scaled);
517  boxDestroy(&scaled_box);
518 }
double m() const
Definition: linlsq.cpp:101
double rms(double m, double c) const
Definition: linlsq.cpp:131
static uinT8 ClipToByte(double pixel)
Definition: imagefind.cpp:382
#define MIN(x, y)
Definition: ndminx.h:28
static uinT32 ComposeRGB(uinT32 r, uinT32 g, uinT32 b)
Definition: imagefind.cpp:375
void add(double x, double y)
Definition: linlsq.cpp:49
inT16 bottom() const
Definition: rect.h:61
inT16 left() const
Definition: rect.h:68
#define MAX(x, y)
Definition: ndminx.h:24
const double kRMSFitScaling
Definition: imagefind.cpp:53
inT16 top() const
Definition: rect.h:54
unsigned int uinT32
Definition: host.h:36
inT16 right() const
Definition: rect.h:75
const int kMinColorDifference
Definition: imagefind.cpp:55
double c(double m) const
Definition: linlsq.cpp:117
Definition: statistc.h:33
#define ASSERT_HOST(x)
Definition: errcode.h:84
Definition: linlsq.h:26

◆ ConnCompAndRectangularize()

void tesseract::ImageFind::ConnCompAndRectangularize ( Pix *  pix,
Boxa **  boxa,
Pixa **  pixa 
)
static

Definition at line 143 of file imagefind.cpp.

143  {
144  *boxa = NULL;
145  *pixa = NULL;
146 
148  pixWrite("junkconncompimage.png", pix, IFF_PNG);
149  // Find the individual image regions in the mask image.
150  *boxa = pixConnComp(pix, pixa, 8);
151  // Rectangularize the individual images. If a sharp edge in vertical and/or
152  // horizontal occupancy can be found, it indicates a probably rectangular
153  // image with unwanted bits merged on, so clip to the approximate rectangle.
154  int npixes = pixaGetCount(*pixa);
155  for (int i = 0; i < npixes; ++i) {
156  int x_start, x_end, y_start, y_end;
157  Pix* img_pix = pixaGetPix(*pixa, i, L_CLONE);
158  pixDisplayWrite(img_pix, textord_tabfind_show_images);
162  &x_start, &y_start, &x_end, &y_end)) {
163  Pix* simple_pix = pixCreate(x_end - x_start, y_end - y_start, 1);
164  pixSetAll(simple_pix);
165  pixDestroy(&img_pix);
166  // pixaReplacePix takes ownership of the simple_pix.
167  pixaReplacePix(*pixa, i, simple_pix, NULL);
168  img_pix = pixaGetPix(*pixa, i, L_CLONE);
169  // Fix the box to match the new pix.
170  l_int32 x, y, width, height;
171  boxaGetBoxGeometry(*boxa, i, &x, &y, &width, &height);
172  Box* simple_box = boxCreate(x + x_start, y + y_start,
173  x_end - x_start, y_end - y_start);
174  boxaReplaceBox(*boxa, i, simple_box);
175  }
176  pixDestroy(&img_pix);
177  }
178 }
const double kMaxRectangularGradient
Definition: imagefind.cpp:49
const double kMinRectangularFraction
Definition: imagefind.cpp:44
int textord_tabfind_show_images
Definition: imagefind.cpp:38
static bool pixNearlyRectangular(Pix *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:252
const double kMaxRectangularFraction
Definition: imagefind.cpp:46

◆ CountPixelsInRotatedBox()

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

Definition at line 583 of file imagefind.cpp.

584  {
585  // Intersect it with the image box.
586  box &= im_box; // This is in-place box intersection.
587  if (box.null_box())
588  return 0;
589  box.rotate(rotation);
590  TBOX rotated_im_box(im_box);
591  rotated_im_box.rotate(rotation);
592  Pix* rect_pix = pixCreate(box.width(), box.height(), 1);
593  pixRasterop(rect_pix, 0, 0, box.width(), box.height(),
594  PIX_SRC, pix, box.left() - rotated_im_box.left(),
595  rotated_im_box.top() - box.top());
596  l_int32 result;
597  pixCountPixels(rect_pix, &result, NULL);
598  pixDestroy(&rect_pix);
599  return result;
600 }
void rotate(const FCOORD &vec)
Definition: rect.h:189
inT16 width() const
Definition: rect.h:111
bool null_box() const
Definition: rect.h:46
inT16 left() const
Definition: rect.h:68
inT16 height() const
Definition: rect.h:104
inT16 top() const
Definition: rect.h:54
Definition: rect.h:30

◆ FindImagePartitions()

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

Definition at line 1284 of file imagefind.cpp.

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

◆ FindImages()

Pix * tesseract::ImageFind::FindImages ( Pix *  pix)
static

Definition at line 65 of file imagefind.cpp.

65  {
66  // Not worth looking at small images.
67  if (pixGetWidth(pix) < kMinImageFindSize ||
68  pixGetHeight(pix) < kMinImageFindSize)
69  return pixCreate(pixGetWidth(pix), pixGetHeight(pix), 1);
70 
71  // Reduce by factor 2.
72  Pix *pixr = pixReduceRankBinaryCascade(pix, 1, 0, 0, 0);
73  pixDisplayWrite(pixr, textord_tabfind_show_images);
74 
75  // Get the halftone mask directly from Leptonica.
76  //
77  // Leptonica will print an error message and return NULL if we call
78  // pixGenHalftoneMask(pixr, NULL, ...) with too small image, so we
79  // want to bypass that.
80  if (pixGetWidth(pixr) < kMinImageFindSize ||
81  pixGetHeight(pixr) < kMinImageFindSize) {
82  pixDestroy(&pixr);
83  return pixCreate(pixGetWidth(pix), pixGetHeight(pix), 1);
84  }
85  l_int32 ht_found = 0;
86  Pix *pixht2 = pixGenHalftoneMask(pixr, NULL, &ht_found,
88  pixDestroy(&pixr);
89  if (!ht_found && pixht2 != NULL)
90  pixDestroy(&pixht2);
91  if (pixht2 == NULL)
92  return pixCreate(pixGetWidth(pix), pixGetHeight(pix), 1);
93 
94  // Expand back up again.
95  Pix *pixht = pixExpandReplicate(pixht2, 2);
96  pixDisplayWrite(pixht, textord_tabfind_show_images);
97  pixDestroy(&pixht2);
98 
99  // Fill to capture pixels near the mask edges that were missed
100  Pix *pixt = pixSeedfillBinary(NULL, pixht, pix, 8);
101  pixOr(pixht, pixht, pixt);
102  pixDestroy(&pixt);
103 
104  // Eliminate lines and bars that may be joined to images.
105  Pix* pixfinemask = pixReduceRankBinaryCascade(pixht, 1, 1, 3, 3);
106  pixDilateBrick(pixfinemask, pixfinemask, 5, 5);
107  pixDisplayWrite(pixfinemask, textord_tabfind_show_images);
108  Pix* pixreduced = pixReduceRankBinaryCascade(pixht, 1, 1, 1, 1);
109  Pix* pixreduced2 = pixReduceRankBinaryCascade(pixreduced, 3, 3, 3, 0);
110  pixDestroy(&pixreduced);
111  pixDilateBrick(pixreduced2, pixreduced2, 5, 5);
112  Pix* pixcoarsemask = pixExpandReplicate(pixreduced2, 8);
113  pixDestroy(&pixreduced2);
114  pixDisplayWrite(pixcoarsemask, textord_tabfind_show_images);
115  // Combine the coarse and fine image masks.
116  pixAnd(pixcoarsemask, pixcoarsemask, pixfinemask);
117  pixDestroy(&pixfinemask);
118  // Dilate a bit to make sure we get everything.
119  pixDilateBrick(pixcoarsemask, pixcoarsemask, 3, 3);
120  Pix* pixmask = pixExpandReplicate(pixcoarsemask, 16);
121  pixDestroy(&pixcoarsemask);
123  pixWrite("junkexpandedcoarsemask.png", pixmask, IFF_PNG);
124  // And the image mask with the line and bar remover.
125  pixAnd(pixht, pixht, pixmask);
126  pixDestroy(&pixmask);
128  pixWrite("junkfinalimagemask.png", pixht, IFF_PNG);
129  // Make the result image the same size as the input.
130  Pix* result = pixCreate(pixGetWidth(pix), pixGetHeight(pix), 1);
131  pixOr(result, result, pixht);
132  pixDestroy(&pixht);
133  return result;
134 }
int textord_tabfind_show_images
Definition: imagefind.cpp:38
const int kMinImageFindSize
Definition: imagefind.cpp:51

◆ pixNearlyRectangular()

bool tesseract::ImageFind::pixNearlyRectangular ( Pix *  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 252 of file imagefind.cpp.

256  {
257  ASSERT_HOST(pix != NULL);
258  *x_start = 0;
259  *x_end = pixGetWidth(pix);
260  *y_start = 0;
261  *y_end = pixGetHeight(pix);
262 
263  uinT32* data = pixGetData(pix);
264  int wpl = pixGetWpl(pix);
265  bool any_cut = false;
266  bool left_done = false;
267  bool right_done = false;
268  bool top_done = false;
269  bool bottom_done = false;
270  do {
271  any_cut = false;
272  // Find the top/bottom edges.
273  int width = *x_end - *x_start;
274  int min_count = static_cast<int>(width * min_fraction);
275  int max_count = static_cast<int>(width * max_fraction);
276  int edge_width = static_cast<int>(width * max_skew_gradient);
277  if (HScanForEdge(data, wpl, *x_start, *x_end, min_count, edge_width,
278  max_count, *y_end, 1, y_start) && !top_done) {
279  top_done = true;
280  any_cut = true;
281  }
282  --(*y_end);
283  if (HScanForEdge(data, wpl, *x_start, *x_end, min_count, edge_width,
284  max_count, *y_start, -1, y_end) && !bottom_done) {
285  bottom_done = true;
286  any_cut = true;
287  }
288  ++(*y_end);
289 
290  // Find the left/right edges.
291  int height = *y_end - *y_start;
292  min_count = static_cast<int>(height * min_fraction);
293  max_count = static_cast<int>(height * max_fraction);
294  edge_width = static_cast<int>(height * max_skew_gradient);
295  if (VScanForEdge(data, wpl, *y_start, *y_end, min_count, edge_width,
296  max_count, *x_end, 1, x_start) && !left_done) {
297  left_done = true;
298  any_cut = true;
299  }
300  --(*x_end);
301  if (VScanForEdge(data, wpl, *y_start, *y_end, min_count, edge_width,
302  max_count, *x_start, -1, x_end) && !right_done) {
303  right_done = true;
304  any_cut = true;
305  }
306  ++(*x_end);
307  } while (any_cut);
308 
309  // All edges must satisfy the condition of sharp gradient in pixel density
310  // in order for the full rectangle to be present.
311  return left_done && right_done && top_done && bottom_done;
312 }
unsigned int uinT32
Definition: host.h:36
#define ASSERT_HOST(x)
Definition: errcode.h:84

◆ TransferImagePartsToImageMask()

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

Definition at line 1231 of file imagefind.cpp.

1233  {
1234  // Extract the noise parts from the grid and put them on a temporary list.
1235  ColPartition_LIST parts_list;
1236  ColPartition_IT part_it(&parts_list);
1237  ColPartitionGridSearch gsearch(part_grid);
1238  gsearch.StartFullSearch();
1239  ColPartition* part;
1240  while ((part = gsearch.NextFullSearch()) != NULL) {
1241  BlobRegionType type = part->blob_type();
1242  if (type == BRT_NOISE || type == BRT_RECTIMAGE || type == BRT_POLYIMAGE) {
1243  part_it.add_after_then_move(part);
1244  gsearch.RemoveBBox();
1245  }
1246  }
1247  // Render listed noise partitions to the image mask.
1248  MarkAndDeleteImageParts(rerotation, part_grid, &parts_list, image_mask);
1249 }
GridSearch< ColPartition, ColPartition_CLIST, ColPartition_C_IT > ColPartitionGridSearch
Definition: colpartition.h:932
BlobRegionType
Definition: blobbox.h:57

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