// Draws the data in a new window. void ImageData::Display() const { #ifndef GRAPHICS_DISABLED const int kTextSize = 64; // Draw the image. Pix* pix = GetPix(); if (pix == NULL) return; int width = pixGetWidth(pix); int height = pixGetHeight(pix); ScrollView* win = new ScrollView("Imagedata", 100, 100, 2 * (width + 2 * kTextSize), 2 * (height + 4 * kTextSize), width + 10, height + 3 * kTextSize, true); win->Image(pix, 0, height - 1); pixDestroy(&pix); // Draw the boxes. win->Pen(ScrollView::RED); win->Brush(ScrollView::NONE); win->TextAttributes("Arial", kTextSize, false, false, false); for (int b = 0; b < boxes_.size(); ++b) { boxes_[b].plot(win); win->Text(boxes_[b].left(), height + kTextSize, box_texts_[b].string()); TBOX scaled(boxes_[b]); scaled.scale(256.0 / height); scaled.plot(win); } // The full transcription. win->Pen(ScrollView::CYAN); win->Text(0, height + kTextSize * 2, transcription_.string()); // Add the features. win->Pen(ScrollView::GREEN); win->Update(); window_wait(win); #endif }
// Create a window and display the projection in it. void TextlineProjection::DisplayProjection() const { #ifndef GRAPHICS_DISABLED int width = pixGetWidth(pix_); int height = pixGetHeight(pix_); Pix* pixc = pixCreate(width, height, 32); int src_wpl = pixGetWpl(pix_); int col_wpl = pixGetWpl(pixc); uint32_t* src_data = pixGetData(pix_); uint32_t* col_data = pixGetData(pixc); for (int y = 0; y < height; ++y, src_data += src_wpl, col_data += col_wpl) { for (int x = 0; x < width; ++x) { int pixel = GET_DATA_BYTE(src_data, x); l_uint32 result; if (pixel <= 17) composeRGBPixel(0, 0, pixel * 15, &result); else if (pixel <= 145) composeRGBPixel(0, (pixel - 17) * 2, 255, &result); else composeRGBPixel((pixel - 145) * 2, 255, 255, &result); col_data[x] = result; } } ScrollView* win = new ScrollView("Projection", 0, 0, width, height, width, height); win->Image(pixc, 0, 0); win->Update(); pixDestroy(&pixc); #endif // GRAPHICS_DISABLED }
// Draws the data in a new window. void ImageData::Display() const { const int kTextSize = 64; int x_max, y_max; WordFeature::ComputeSize(features_, &x_max, &y_max); ScrollView* win = new ScrollView("Imagedata", 100, 100, 2 * (x_max + 2 * kTextSize), 2 * (y_max + 4 * kTextSize), x_max + 10, y_max + 3 * kTextSize, true); // Draw the image. Pix* pix = GetPix(); int height = 256; if (pix != NULL) { height = pixGetHeight(pix); win->Image(pix, 0, height - 1); pixDestroy(&pix); } // Draw the boxes. win->Pen(ScrollView::RED); win->Brush(ScrollView::NONE); win->TextAttributes("Arial", kTextSize, false, false, false); for (int b = 0; b < boxes_.size(); ++b) { boxes_[b].plot(win); win->Text(boxes_[b].left(), y_max + kTextSize, box_texts_[b].string()); TBOX scaled(boxes_[b]); scaled.scale(256.0 / height); scaled.plot(win); } // The full transcription. win->Pen(ScrollView::CYAN); win->Text(0, y_max + kTextSize * 2, transcription_.string()); // Add the features. win->Pen(ScrollView::GREEN); WordFeature::Draw(features_, win); win->Update(); window_wait(win); }
// 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; }