Exemplo n.º 1
0
// Rotate the grid by rotation, keeping cell contents.
// rotation must be a multiple of 90 degrees.
// NOTE: due to partial cells, cell coverage in the rotated grid will be
// inexact. This is why there is no Rotate for the generic BBGrid.
// TODO(rays) investigate fixing this inaccuracy by moving the origin after
// rotation.
void IntGrid::Rotate(const FCOORD& rotation) {
  ASSERT_HOST(rotation.x() == 0.0f || rotation.y() == 0.0f);
  ICOORD old_bleft(bleft());
  ICOORD old_tright(tright());
  int old_width = gridwidth();
  int old_height = gridheight();
  TBOX box(bleft(), tright());
  box.rotate(rotation);
  int* old_grid = grid_;
  grid_ = NULL;
  Init(gridsize(), box.botleft(), box.topright());
  // Iterate over the old grid, copying data to the rotated position in the new.
  int oldi = 0;
  FCOORD x_step(rotation);
  x_step *= gridsize();
  for (int oldy = 0; oldy < old_height; ++oldy) {
    FCOORD line_pos(old_bleft.x(), old_bleft.y() + gridsize() * oldy);
    line_pos.rotate(rotation);
    for (int oldx = 0; oldx < old_width; ++oldx, line_pos += x_step, ++oldi) {
      int grid_x, grid_y;
      GridCoords(static_cast<int>(line_pos.x() + 0.5),
                 static_cast<int>(line_pos.y() + 0.5),
                 &grid_x, &grid_y);
      grid_[grid_y * gridwidth() + grid_x] = old_grid[oldi];
    }
  }
  delete [] old_grid;
}
Exemplo n.º 2
0
// Returns a full-resolution binary pix in which each cell over the given
// threshold is filled as a black square. pixDestroy after use.
// Edge cells, which have a zero 4-neighbour, are not marked.
Pix* IntGrid::ThresholdToPix(int threshold) const {
  Pix* pix = pixCreate(tright().x() - bleft().x(),
                       tright().y() - bleft().y(), 1);
  int cellsize = gridsize();
  for (int y = 0; y < gridheight(); ++y) {
    for (int x = 0; x < gridwidth(); ++x) {
      if (GridCellValue(x, y) > threshold &&
          GridCellValue(x - 1, y) > 0 && GridCellValue(x + 1, y) > 0 &&
              GridCellValue(x, y - 1) > 0 && GridCellValue(x, y + 1) > 0) {
        pixRasterop(pix, x * cellsize, tright().y() - ((y + 1) * cellsize),
                    cellsize, cellsize, PIX_SET, NULL, 0, 0);
      }
    }
  }
  return pix;
}
Exemplo n.º 3
0
// Computes and returns the noise_density IntGrid, at the same gridsize as
// this by summing the number of small elements in a 3x3 neighbourhood of
// each grid cell. good_grid is filled with blobs that are considered most
// likely good text, and this is filled with small and medium blobs that are
// more likely non-text.
// The photo_map is used to bias the decision towards non-text, rather than
// supplying definite decision.
IntGrid* CCNonTextDetect::ComputeNoiseDensity(bool debug, Pix* photo_map,
        BlobGrid* good_grid) {
    IntGrid* noise_counts = CountCellElements();
    IntGrid* noise_density = noise_counts->NeighbourhoodSum();
    IntGrid* good_counts = good_grid->CountCellElements();
    // Now increase noise density in photo areas, to bias the decision and
    // minimize hallucinated text on image, but trim the noise_density where
    // there are good blobs and the original count is low in non-photo areas,
    // indicating that most of the result came from neighbouring cells.
    int height = pixGetHeight(photo_map);
    int photo_offset = IntCastRounded(max_noise_count_ * kPhotoOffsetFraction);
    for (int y = 0; y < gridheight(); ++y) {
        for (int x = 0; x < gridwidth(); ++x) {
            int noise = noise_density->GridCellValue(x, y);
            if (max_noise_count_ < noise + photo_offset &&
                    noise <= max_noise_count_) {
                // Test for photo.
                int left = x * gridsize();
                int right = left + gridsize();
                int bottom = height - y * gridsize();
                int top = bottom - gridsize();
                if (ImageFind::BoundsWithinRect(photo_map, &left, &top, &right,
                                                &bottom)) {
                    noise_density->SetGridCell(x, y, noise + photo_offset);
                }
            }
            if (debug && noise > max_noise_count_ &&
                    good_counts->GridCellValue(x, y) > 0) {
                tprintf("At %d, %d, noise = %d, good=%d, orig=%d, thr=%d\n",
                        x * gridsize(), y * gridsize(),
                        noise_density->GridCellValue(x, y),
                        good_counts->GridCellValue(x, y),
                        noise_counts->GridCellValue(x, y), max_noise_count_);
            }
            if (noise > max_noise_count_ &&
                    good_counts->GridCellValue(x, y) > 0 &&
                    noise_counts->GridCellValue(x, y) * kOriginalNoiseMultiple <=
                    max_noise_count_) {
                noise_density->SetGridCell(x, y, 0);
            }
        }
    }
    delete noise_counts;
    delete good_counts;
    return noise_density;
}
Exemplo n.º 4
0
// Returns a new IntGrid containing values equal to the sum of all the
// neighbouring cells. The returned grid must be deleted after use.
// For ease of implementation, edge cells are double counted, to make them
// have the same range as the non-edge cells.
IntGrid* IntGrid::NeighbourhoodSum() const {
  IntGrid* sumgrid = new IntGrid(gridsize(), bleft(), tright());
  for (int y = 0; y < gridheight(); ++y) {
    for (int x = 0; x < gridwidth(); ++x) {
      int cell_count = 0;
      for (int yoffset = -1; yoffset <= 1; ++yoffset) {
        for (int xoffset = -1; xoffset <= 1; ++xoffset) {
          int grid_x = x + xoffset;
          int grid_y = y + yoffset;
          ClipGridCoords(&grid_x, &grid_y);
          cell_count += GridCellValue(grid_x, grid_y);
        }
      }
      if (GridCellValue(x, y) > 1)
        sumgrid->SetGridCell(x, y, cell_count);
    }
  }
  return sumgrid;
}