Skip to main content

LineSegmenter

Struct LineSegmenter 

Source
pub struct LineSegmenter { /* private fields */ }
Expand description

Line segmenter using horizontal projection profile

This segmenter detects text lines in a document image by analyzing the horizontal projection profile - the sum of dark pixels in each row.

§Algorithm

  1. Convert image to grayscale and binarize (threshold at 128)
  2. Suppress printed rules — page borders, table rules, underlines — so their ink floor cannot hide every gap; see suppress_page_rules
  3. Compute horizontal projection profile (sum of dark pixels per row)
  4. Apply smoothing to reduce noise
  5. Find gaps between text regions (where projection is near zero)
  6. Extract each text region as a separate line

§Parameters

  • min_line_height: Minimum height to consider as a valid text line
  • smooth_window: Window size for smoothing the projection profile
  • density_threshold_ratio: Fraction of mean row density that still counts as a gap

Implementations§

Source§

impl LineSegmenter

Source

pub fn new(min_line_height: u32, smooth_window: u32) -> Self

Create a new line segmenter with specified parameters

§Arguments
  • min_line_height - Minimum height in pixels to consider as a valid text line
  • smooth_window - Window size for smoothing the projection profile (1 = no smoothing)
§Returns

A new LineSegmenter instance

§Example
use monocr_onnx::segmenter::LineSegmenter;

// Create segmenter with default parameters
let segmenter = LineSegmenter::new(10, 3);
Source

pub fn with_density_ratio( min_line_height: u32, smooth_window: u32, density_threshold_ratio: f32, ) -> Self

Create a segmenter with an explicit gap threshold ratio.

See crate::MonOcrBuilder::density_threshold_ratio for what the ratio does and why it is worth setting per input class. The caller is responsible for passing a finite, positive ratio; the builder validates it.

Source

pub fn segment(&self, image_path: impl AsRef<Path>) -> Result<Vec<LineSegment>>

Segment an image into text lines

This is the main method that performs line segmentation on a document image. It uses horizontal projection profile analysis to detect text lines.

§Arguments
  • image_path - Path to the image file
§Returns
  • Ok(Vec<LineSegment>) - Vector of segmented lines with images and bounding boxes
  • Err(anyhow::Error) - If the image cannot be opened or processed
§Algorithm Details
  1. Binarization: Convert to grayscale and threshold at 128 (pixels < 128 are text)
  2. Rule suppression: Remove printed rules, so a page border cannot fuse the whole page into one band (suppress_page_rules)
  3. Projection: Compute horizontal projection profile (sum of text pixels per row)
  4. Smoothing: Apply moving average filter if smooth_window > 1
  5. Gap Detection: Find gaps where the RAW projection is below density_threshold_ratio of the SMOOTHED profile’s mean non-empty row density (default 5%). The two profiles are deliberately different: the smoothed mean is the steadier calibration, and the raw profile is the only one that still reaches zero between tightly set lines
  6. Line Extraction: Extract each region between gaps as a separate line
  7. Padding: Add 4-pixel padding around each line for edge character capture
§Polarity

The threshold treats dark as ink, so a light-on-dark page must be inverted before it reaches here or the BACKGROUND is what gets segmented. crate::normalize_polarity is that step and MonOcr::predict_page runs it. This method does not, because it is also the entry point for a caller who has already corrected polarity.

Source

pub fn segment_image(&self, gray_img: &GrayImage) -> Result<Vec<LineSegment>>

Segment an image that is already decoded and grayscale.

The path-taking Self::segment is a thin wrapper over this. The split exists because polarity has to be corrected BEFORE segmentation — the threshold below treats dark as ink, so a light-on-dark page segments the BACKGROUND and returns the gaps between lines — and the caller doing that correction is holding an image, not a path. go/monocr.go’s predictImage and js/src/monocr.js’s normalizePageForSegmentation are the same arrangement.

Auto Trait Implementations§

Blanket Implementations§

Source§

impl<T> Any for T
where T: 'static + ?Sized,

Source§

fn type_id(&self) -> TypeId

Gets the TypeId of self. Read more
Source§

impl<T> Borrow<T> for T
where T: ?Sized,

Source§

fn borrow(&self) -> &T

Immutably borrows from an owned value. Read more
Source§

impl<T> BorrowMut<T> for T
where T: ?Sized,

Source§

fn borrow_mut(&mut self) -> &mut T

Mutably borrows from an owned value. Read more
Source§

impl<T> From<T> for T

Source§

fn from(t: T) -> T

Returns the argument unchanged.

Source§

impl<T> Instrument for T

Source§

fn instrument(self, span: Span) -> Instrumented<Self>

Instruments this type with the provided Span, returning an Instrumented wrapper. Read more
Source§

fn in_current_span(self) -> Instrumented<Self>

Instruments this type with the current Span, returning an Instrumented wrapper. Read more
Source§

impl<T, U> Into<U> for T
where U: From<T>,

Source§

fn into(self) -> U

Calls U::from(self).

That is, this conversion is whatever the implementation of From<T> for U chooses to do.

Source§

impl<T> IntoEither for T

Source§

fn into_either(self, into_left: bool) -> Either<Self, Self>

Converts self into a Left variant of Either<Self, Self> if into_left is true. Converts self into a Right variant of Either<Self, Self> otherwise. Read more
Source§

fn into_either_with<F>(self, into_left: F) -> Either<Self, Self>
where F: FnOnce(&Self) -> bool,

Converts self into a Left variant of Either<Self, Self> if into_left(&self) returns true. Converts self into a Right variant of Either<Self, Self> otherwise. Read more
Source§

impl<T> Pointable for T

Source§

const ALIGN: usize

The alignment of pointer.
Source§

type Init = T

The type for initializers.
Source§

unsafe fn init(init: <T as Pointable>::Init) -> usize

Initializes a with the given initializer. Read more
Source§

unsafe fn deref<'a>(ptr: usize) -> &'a T

Dereferences the given pointer. Read more
Source§

unsafe fn deref_mut<'a>(ptr: usize) -> &'a mut T

Mutably dereferences the given pointer. Read more
Source§

unsafe fn drop(ptr: usize)

Drops the object pointed to by the given pointer. Read more
Source§

impl<T, U> TryFrom<U> for T
where U: Into<T>,

Source§

type Error = !

The type returned in the event of a conversion error.
Source§

fn try_from(value: U) -> Result<T, !>

Performs the conversion.
Source§

impl<T, U> TryInto<U> for T
where U: TryFrom<T>,

Source§

type Error = <U as TryFrom<T>>::Error

The type returned in the event of a conversion error.
Source§

fn try_into(self) -> Result<U, <U as TryFrom<T>>::Error>

Performs the conversion.
Source§

impl<T> WithSubscriber for T

Source§

fn with_subscriber<S>(self, subscriber: S) -> WithDispatch<Self>
where S: Into<Dispatch>,

Attaches the provided Subscriber to this type, returning a WithDispatch wrapper. Read more
Source§

fn with_current_subscriber(self) -> WithDispatch<Self>

Attaches the current default Subscriber to this type, returning a WithDispatch wrapper. Read more