Esempio 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;
}
Esempio n. 2
0
// Tests each blob in the list to see if it is certain non-text using 2
// conditions:
// 1. blob overlaps a cell with high value in noise_density_ (previously set
// by ComputeNoiseDensity).
// OR 2. The blob overlaps more than max_blob_overlaps in *this grid. This
// condition is disabled with max_blob_overlaps == -1.
// If it does, the blob is declared non-text, and is used to mark up the
// nontext_mask. Such blobs are fully deleted, and non-noise blobs have their
// neighbours reset, as they may now point to deleted data.
// WARNING: The blobs list blobs may be in the *this grid, but they are
// not removed. If any deleted blobs might be in *this, then this must be
// Clear()ed immediately after MarkAndDeleteNonTextBlobs is called.
// If the win is not NULL, deleted blobs are drawn on it in red, and kept
// blobs are drawn on it in ok_color.
void CCNonTextDetect::MarkAndDeleteNonTextBlobs(BLOBNBOX_LIST* blobs,
        int max_blob_overlaps,
        ScrollView* win,
        ScrollView::Color ok_color,
        Pix* nontext_mask) {
    int imageheight = tright().y() - bleft().x();
    BLOBNBOX_IT blob_it(blobs);
    BLOBNBOX_LIST dead_blobs;
    BLOBNBOX_IT dead_it(&dead_blobs);
    for (blob_it.mark_cycle_pt(); !blob_it.cycled_list(); blob_it.forward()) {
        BLOBNBOX* blob = blob_it.data();
        TBOX box = blob->bounding_box();
        if (!noise_density_->RectMostlyOverThreshold(box, max_noise_count_) &&
                (max_blob_overlaps < 0 ||
                 !BlobOverlapsTooMuch(blob, max_blob_overlaps))) {
            blob->ClearNeighbours();
#ifndef GRAPHICS_DISABLED
            if (win != NULL)
                blob->plot(win, ok_color, ok_color);
#endif  // GRAPHICS_DISABLED
        } else {
            if (noise_density_->AnyZeroInRect(box)) {
                // There is a danger that the bounding box may overlap real text, so
                // we need to render the outline.
                Pix* blob_pix = blob->cblob()->render_outline();
                pixRasterop(nontext_mask, box.left(), imageheight - box.top(),
                            box.width(), box.height(), PIX_SRC | PIX_DST,
                            blob_pix, 0, 0);
                pixDestroy(&blob_pix);
            } else {
                if (box.area() < gridsize() * gridsize()) {
                    // It is a really bad idea to make lots of small components in the
                    // photo mask, so try to join it to a bigger area by expanding the
                    // box in a way that does not touch any zero noise density cell.
                    box = AttemptBoxExpansion(box, *noise_density_, gridsize());
                }
                // All overlapped cells are non-zero, so just mark the rectangle.
                pixRasterop(nontext_mask, box.left(), imageheight - box.top(),
                            box.width(), box.height(), PIX_SET, NULL, 0, 0);
            }
#ifndef GRAPHICS_DISABLED
            if (win != NULL)
                blob->plot(win, ScrollView::RED, ScrollView::RED);
#endif  // GRAPHICS_DISABLED
            // It is safe to delete the cblob now, as it isn't used by the grid
            // or BlobOverlapsTooMuch, and the BLOBNBOXes will go away with the
            // dead_blobs list.
            // TODO(rays) delete the delete when the BLOBNBOX destructor deletes
            // the cblob.
            delete blob->cblob();
            dead_it.add_to_end(blob_it.extract());
        }
    }
}
Esempio n. 3
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;
}
Esempio 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;
}
Esempio n. 5
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;
}
Esempio n. 6
0
// Creates and returns a Pix with the same resolution as the original
// in which 1 (black) pixels represent likely non text (photo, line drawing)
// areas of the page, deleting from the blob_block the blobs that were
// determined to be non-text.
// The photo_map is used to bias the decision towards non-text, rather than
// supplying definite decision.
// The blob_block is the usual result of connected component analysis,
// holding the detected blobs.
// The returned Pix should be PixDestroyed after use.
Pix* CCNonTextDetect::ComputeNonTextMask(bool debug, Pix* photo_map,
        TO_BLOCK* blob_block) {
    // Insert the smallest blobs into the grid.
    InsertBlobList(&blob_block->small_blobs);
    InsertBlobList(&blob_block->noise_blobs);
    // Add the medium blobs that don't have a good strokewidth neighbour.
    // Those that do go into good_grid as an antidote to spreading beyond the
    // real reaches of a noise region.
    BlobGrid good_grid(gridsize(), bleft(), tright());
    BLOBNBOX_IT blob_it(&blob_block->blobs);
    for (blob_it.mark_cycle_pt(); !blob_it.cycled_list(); blob_it.forward()) {
        BLOBNBOX* blob = blob_it.data();
        double perimeter_area_ratio = blob->cblob()->perimeter() / 4.0;
        perimeter_area_ratio *= perimeter_area_ratio / blob->enclosed_area();
        if (blob->GoodTextBlob() == 0 || perimeter_area_ratio < kMinGoodTextPARatio)
            InsertBBox(true, true, blob);
        else
            good_grid.InsertBBox(true, true, blob);
    }
    noise_density_ = ComputeNoiseDensity(debug, photo_map, &good_grid);
    good_grid.Clear();  // Not needed any more.
    Pix* pix = noise_density_->ThresholdToPix(max_noise_count_);
    if (debug) {
        pixWrite("junknoisemask.png", pix, IFF_PNG);
    }
    ScrollView* win = NULL;
#ifndef GRAPHICS_DISABLED
    if (debug) {
        win = MakeWindow(0, 400, "Photo Mask Blobs");
    }
#endif  // GRAPHICS_DISABLED
    // Large and medium blobs are not text if they overlap with "a lot" of small
    // blobs.
    MarkAndDeleteNonTextBlobs(&blob_block->large_blobs,
                              kMaxLargeOverlapsWithSmall,
                              win, ScrollView::DARK_GREEN, pix);
    MarkAndDeleteNonTextBlobs(&blob_block->blobs, kMaxMediumOverlapsWithSmall,
                              win, ScrollView::WHITE, pix);
    // Clear the grid of small blobs and insert the medium blobs.
    Clear();
    InsertBlobList(&blob_block->blobs);
    MarkAndDeleteNonTextBlobs(&blob_block->large_blobs,
                              kMaxLargeOverlapsWithMedium,
                              win, ScrollView::DARK_GREEN, pix);
    // Clear again before we start deleting the blobs in the grid.
    Clear();
    MarkAndDeleteNonTextBlobs(&blob_block->noise_blobs, -1,
                              win, ScrollView::CORAL, pix);
    MarkAndDeleteNonTextBlobs(&blob_block->small_blobs, -1,
                              win, ScrollView::GOLDENROD, pix);
    MarkAndDeleteNonTextBlobs(&blob_block->blobs, -1,
                              win, ScrollView::WHITE, pix);
    if (debug) {
#ifndef GRAPHICS_DISABLED
        win->Update();
#endif  // GRAPHICS_DISABLED
        pixWrite("junkccphotomask.png", pix, IFF_PNG);
#ifndef GRAPHICS_DISABLED
        delete win->AwaitEvent(SVET_DESTROY);
        delete win;
#endif  // GRAPHICS_DISABLED
    }
    return pix;
}
Esempio n. 7
0
// Search vertically for a blob that is aligned with the input bbox.
// The search parameters are determined by AlignedBlobParams.
// top_to_bottom tells whether to search down or up.
// The return value is nullptr if nothing was found in the search box
// or if a blob was found in the gutter. On a nullptr return, end_y
// is set to the edge of the search box or the leading edge of the
// gutter blob if one was found.
BLOBNBOX* AlignedBlob::FindAlignedBlob(const AlignedBlobParams& p,
                                       bool top_to_bottom, BLOBNBOX* bbox,
                                       int x_start, int* end_y) {
  TBOX box = bbox->bounding_box();
  // If there are separator lines, get the column edges.
  int left_column_edge = bbox->left_rule();
  int right_column_edge = bbox->right_rule();
  // start_y is used to guarantee that forward progress is made and the
  // search does not go into an infinite loop. New blobs must extend the
  // line beyond start_y.
  int start_y = top_to_bottom ? box.bottom() : box.top();
  if (WithinTestRegion(2, x_start, start_y)) {
    tprintf("Column edges for blob at (%d,%d)->(%d,%d) are [%d, %d]\n",
            box.left(), box.top(), box.right(), box.bottom(),
            left_column_edge, right_column_edge);
  }
  // Compute skew tolerance.
  int skew_tolerance = p.max_v_gap / kMaxSkewFactor;
  // Calculate xmin and xmax of the search box so that it contains
  // all possibly relevant boxes up to p.max_v_gap above or below accoording
  // to top_to_bottom.
  // Start with a notion of vertical with the current estimate.
  int x2 = (p.max_v_gap * p.vertical.x() + p.vertical.y()/2) / p.vertical.y();
  if (top_to_bottom) {
    x2 = x_start - x2;
    *end_y = start_y - p.max_v_gap;
  } else {
    x2 = x_start + x2;
    *end_y = start_y + p.max_v_gap;
  }
  // Expand the box by an additional skew tolerance
  int xmin = std::min(x_start, x2) - skew_tolerance;
  int xmax = std::max(x_start, x2) + skew_tolerance;
  // Now add direction-specific tolerances.
  if (p.right_tab) {
    xmax += p.min_gutter;
    xmin -= p.l_align_tolerance;
  } else {
    xmax += p.r_align_tolerance;
    xmin -= p.min_gutter;
  }
  // Setup a vertical search for an aligned blob.
  GridSearch<BLOBNBOX, BLOBNBOX_CLIST, BLOBNBOX_C_IT> vsearch(this);
  if (WithinTestRegion(2, x_start, start_y))
    tprintf("Starting %s %s search at %d-%d,%d, search_size=%d, gutter=%d\n",
            p.ragged ? "Ragged" : "Aligned", p.right_tab ? "Right" : "Left",
            xmin, xmax, start_y, p.max_v_gap, p.min_gutter);
  vsearch.StartVerticalSearch(xmin, xmax, start_y);
  // result stores the best real return value.
  BLOBNBOX* result = nullptr;
  // The backup_result is not a tab candidate and can be used if no
  // real tab candidate result is found.
  BLOBNBOX* backup_result = nullptr;
  // neighbour is the blob that is currently being investigated.
  BLOBNBOX* neighbour = nullptr;
  while ((neighbour = vsearch.NextVerticalSearch(top_to_bottom)) != nullptr) {
    if (neighbour == bbox)
      continue;
    TBOX nbox = neighbour->bounding_box();
    int n_y = (nbox.top() + nbox.bottom()) / 2;
    if ((!top_to_bottom && n_y > start_y + p.max_v_gap) ||
        (top_to_bottom && n_y < start_y - p.max_v_gap)) {
      if (WithinTestRegion(2, x_start, start_y))
        tprintf("Neighbour too far at (%d,%d)->(%d,%d)\n",
                nbox.left(), nbox.bottom(), nbox.right(), nbox.top());
      break;  // Gone far enough.
    }
    // It is CRITICAL to ensure that forward progress is made, (strictly
    // in/decreasing n_y) or the caller could loop infinitely, while
    // waiting for a sequence of blobs in a line to end.
    // NextVerticalSearch alone does not guarantee this, as there may be
    // more than one blob in a grid cell. See comment in AlignTabs.
    if ((n_y < start_y) != top_to_bottom || nbox.y_overlap(box))
      continue;  // Only look in the required direction.
    if (result != nullptr && result->bounding_box().y_gap(nbox) > gridsize())
      return result;  // This result is clear.
    if (backup_result != nullptr && p.ragged && result == nullptr &&
        backup_result->bounding_box().y_gap(nbox) > gridsize())
      return backup_result;  // This result is clear.

    // If the neighbouring blob is the wrong side of a separator line, then it
    // "doesn't exist" as far as we are concerned.
    int x_at_n_y = x_start + (n_y - start_y) * p.vertical.x() / p.vertical.y();
    if (x_at_n_y < neighbour->left_crossing_rule() ||
        x_at_n_y > neighbour->right_crossing_rule())
      continue;  // Separator line in the way.
    int n_left = nbox.left();
    int n_right = nbox.right();
    int n_x = p.right_tab ? n_right : n_left;
    if (WithinTestRegion(2, x_start, start_y))
      tprintf("neighbour at (%d,%d)->(%d,%d), n_x=%d, n_y=%d, xatn=%d\n",
              nbox.left(), nbox.bottom(), nbox.right(), nbox.top(),
              n_x, n_y, x_at_n_y);
    if (p.right_tab &&
        n_left < x_at_n_y + p.min_gutter &&
        n_right > x_at_n_y + p.r_align_tolerance &&
        (p.ragged || n_left < x_at_n_y + p.gutter_fraction * nbox.height())) {
      // In the gutter so end of line.
      if (bbox->right_tab_type() >= TT_MAYBE_ALIGNED)
        bbox->set_right_tab_type(TT_DELETED);
      *end_y = top_to_bottom ? nbox.top() : nbox.bottom();
      if (WithinTestRegion(2, x_start, start_y))
        tprintf("gutter\n");
      return nullptr;
    }
    if (!p.right_tab &&
        n_left < x_at_n_y - p.l_align_tolerance &&
        n_right > x_at_n_y - p.min_gutter &&
        (p.ragged || n_right > x_at_n_y - p.gutter_fraction * nbox.height())) {
      // In the gutter so end of line.
      if (bbox->left_tab_type() >= TT_MAYBE_ALIGNED)
        bbox->set_left_tab_type(TT_DELETED);
      *end_y = top_to_bottom ? nbox.top() : nbox.bottom();
      if (WithinTestRegion(2, x_start, start_y))
        tprintf("gutter\n");
      return nullptr;
    }
    if ((p.right_tab && neighbour->leader_on_right()) ||
        (!p.right_tab && neighbour->leader_on_left()))
      continue;  // Neighbours of leaders are not allowed to be used.
    if (n_x <= x_at_n_y + p.r_align_tolerance &&
        n_x >= x_at_n_y - p.l_align_tolerance) {
      // Aligned so keep it. If it is a marked tab save it as result,
      // otherwise keep it as backup_result to return in case of later failure.
      if (WithinTestRegion(2, x_start, start_y))
        tprintf("aligned, seeking%d, l=%d, r=%d\n",
                p.right_tab, neighbour->left_tab_type(),
                neighbour->right_tab_type());
      TabType n_type = p.right_tab ? neighbour->right_tab_type()
                                   : neighbour->left_tab_type();
      if (n_type != TT_NONE && (p.ragged || n_type != TT_MAYBE_RAGGED)) {
        if (result == nullptr) {
          result = neighbour;
        } else {
          // Keep the closest neighbour by Euclidean distance.
          // This prevents it from picking a tab blob in another column.
          const TBOX& old_box = result->bounding_box();
          int x_diff = p.right_tab ? old_box.right() : old_box.left();
          x_diff -= x_at_n_y;
          int y_diff = (old_box.top() + old_box.bottom()) / 2 - start_y;
          int old_dist = x_diff * x_diff + y_diff * y_diff;
          x_diff = n_x - x_at_n_y;
          y_diff = n_y - start_y;
          int new_dist = x_diff * x_diff + y_diff * y_diff;
          if (new_dist < old_dist)
            result = neighbour;
        }
      } else if (backup_result == nullptr) {
        if (WithinTestRegion(2, x_start, start_y))
          tprintf("Backup\n");
        backup_result = neighbour;
      } else {
        TBOX backup_box = backup_result->bounding_box();
        if ((p.right_tab && backup_box.right() < nbox.right()) ||
            (!p.right_tab && backup_box.left() > nbox.left())) {
          if (WithinTestRegion(2, x_start, start_y))
            tprintf("Better backup\n");
          backup_result = neighbour;
        }
      }
    }
  }
  return result != nullptr ? result : backup_result;
}
int main(int argc, const char *argv[])
{

  // parse arguments ///////////////////////////////////////////
  // Declare the supported options.
  po::options_description desc("Visualize data");
  desc.add_options()
    ("help", "produce help message")
    ("width", po::value<double>()->required(), "Width ")
    ("height", po::value<double>()->required(), "Height ")
    ("dir", po::value<std::string>()->default_value("."), "Data directory")
;

  po::positional_options_description pos;
  pos.add("width", 1);
  pos.add("height", 1);
  pos.add("dir", 1);

  po::variables_map vm;
  po::store(po::command_line_parser(argc, argv).options(desc).positional(pos).run(), vm);
  po::notify(vm);    

  double width = vm["width"].as<double>();
  double height = vm["height"].as<double>();
  std::string datadirectory = vm["dir"].as<std::string>();
  // end of parse arguments ////////////////////////////////////
  cv::Mat laser_pose, laser_ranges, scan_angles;
  loadMat(laser_pose, datadirectory + "/laser_pose_all.bin");
  loadMat(laser_ranges, datadirectory + "/laser_range_all.bin");
  loadMat(scan_angles, datadirectory + "/scan_angles_all.bin");
  cv::Mat laser_reflectance(laser_ranges.rows, laser_ranges.cols, CV_8U);
  std::string floorplanfile = datadirectory + "/floorplan.png";
  cv::Mat floorplan = cv::imread(floorplanfile, cv::IMREAD_GRAYSCALE);
    if(! floorplan.data )                              // Check for invalid input
    {
      std::cout <<  "Could not open or find the image" << std::endl ;
        return -1;
    }
  cv::transpose(floorplan, floorplan);
  cv::flip(floorplan, floorplan, 1);
  cv::Vec2d size_bitmap(width, height);
  cv::Vec2d margin(1, 1);
  cv::Vec2d min_pt(- margin(0) - size_bitmap(0)/2, - margin(1) - size_bitmap(1)/2);
  double max_range = 8;
  cv::Vec2i gridsize(floorplan.size[0], floorplan.size[1]);
  cv::Vec2d cellsize; 
  cv::divide(size_bitmap , gridsize, cellsize);
  //std::cout << cellsize(0) << cellsize(1) << std::endl;
  cv::Vec2i ncells;
  cv::divide(min_pt, cellsize, ncells, -2);

  OccupancyGrid2D<double, int> map(
      min_pt(0), 
      min_pt(1),
      cellsize(0),
      cellsize(1),
      ncells(0),
      ncells(1));
  // initialize map with occupancy with floorplan
  for (int r = 0; r < ncells(0); ++r) {
    for (int c = 0; c < ncells(1); ++c) {
      int fp_r = r - margin(0) / cellsize(0);
      int fp_c = c - margin(1) / cellsize(1);
      if ((0 <= fp_r) && (fp_r < floorplan.rows)
          && (0 <= fp_c) && (fp_c < floorplan.cols)) {
        map.og_.at<uint8_t>(r, c) = (floorplan.at<uint8_t>(fp_r, fp_c) > 127) ? map.FREE : map.OCCUPIED;
      } else {
        map.og_.at<uint8_t>(r, c) = map.OCCUPIED;
      }
    }
  }

  boost::mt19937 gen;
  boost::normal_distribution<> norm_dist(1, NOISE_VARIANCE);
  boost::variate_generator<boost::mt19937&, boost::normal_distribution<> > norm_rand(gen, norm_dist);

  for (int r = 0; r < scan_angles.rows; r++) {
    double* pose = laser_pose.ptr<double>(r);
    double* angles = scan_angles.ptr<double>(r);
    double robot_angle = pose[2];
    for (int c = 0; c < scan_angles.cols; c++) {
      double total_angle = robot_angle + angles[c];
      cv::Vec2d final_pos;
      bool refl;
      double range = map.ray_trace(pose[0], pose[1], total_angle, max_range, final_pos, refl);
      range *= norm_rand();
      laser_ranges.at<double>(r, c) = range;
      laser_reflectance.at<uint8_t>(r, c) = (uint8_t) refl;
    }

    // draw input 
    cv::Mat visin;
    cv::cvtColor(map.og_, visin, cv::COLOR_GRAY2BGR);
    cv::Vec2d position(pose[0], pose[1]);
    map.draw_lasers(visin, position, robot_angle, angles,
        laser_ranges.ptr<double>(r),
        laser_reflectance.ptr<uint8_t>(r),
        scan_angles.cols,
        CV_RGB(0, 255, 0));
    cv::imshow("c", visin);
    cv::waitKey(33);
  }
  saveMat(laser_ranges, "laser_range_all.bin");
  saveMat(laser_reflectance, "laser_reflectance_all.bin");
}
Esempio n. 9
0
// Detects and marks leader dots/dashes.
//    Leaders are horizontal chains of small or noise blobs that look
//    monospace according to ColPartition::MarkAsLeaderIfMonospaced().
// Detected leaders become the only occupants of small_blobs list.
// Non-leader small blobs get moved to the blobs list.
// Non-leader noise blobs remain singletons in the noise list.
// All small and noise blobs in high density regions are marked BTFT_NONTEXT.
void StrokeWidth::FindLeadersAndMarkNoise(bool final, TO_BLOCK* block,
                                          TabFind* line_grid,
                                          ColPartition_LIST* leader_parts) {
  line_grid->InsertBlobList(true, true, false, &block->small_blobs,
                            false, this);
  line_grid->InsertBlobList(true, true, false, &block->noise_blobs,
                            false, this);
  int max_noise_count =
      static_cast<int>(kMaxSmallNeighboursPerPix * gridsize() * gridsize());
  BlobGridSearch gsearch(this);
  BLOBNBOX* bbox;
  // For every bbox in the grid, set its neighbours.
  gsearch.StartFullSearch();
  while ((bbox = gsearch.NextFullSearch()) != NULL) {
    int noise_count = noise_density_->GridCellValue(gsearch.GridX(),
                                                    gsearch.GridY());
    if (noise_count <= max_noise_count) {
      SetNeighbours(true, bbox);
    } else {
      bbox->set_flow(BTFT_NONTEXT);
    }
  }
  ColPartition_IT part_it(leader_parts);
  gsearch.StartFullSearch();