Exemplo n.º 1
0
// Inserts all the blobs from the given list, with x and y spreading,
// without removing from the source list, so ownership remains with the
// source list.
    void BlobGrid::InsertBlobList(BLOBNBOX_LIST * blobs) {
        BLOBNBOX_IT blob_it(blobs);
        for (blob_it.mark_cycle_pt(); !blob_it.cycled_list(); blob_it.forward()) {
            BLOBNBOX *blob = blob_it.data();
            if (!blob->joined_to_prev())
                InsertBBox(true, true, blob);
        }
    }
Exemplo n.º 2
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;
}