libs.processing

Image alignment, per-ROI interpretation, spatial queries, and writing results. Used by extract_logsheet() and related export paths.

formhtr.libs.processing.align_images.validate_corners(corners, height, width, tol=20)[source]

Check that four corners form a plausible document quad.

Parameters:
  • corners – Four (x, y) points in order TL, TR, BR, BL.

  • height – Image height in pixels.

  • width – Image width in pixels.

  • tol – Maximum relative margin (percent of image) for side length mismatch.

Returns:

True if opposite sides match within tolerance.

formhtr.libs.processing.align_images.compute_closest_point(point, corners)[source]

Pick the corner nearest to a reference image corner.

Parameters:
  • point – Reference (x, y).

  • corners – Candidate corner coordinates.

Returns:

The closest corner from corners.

formhtr.libs.processing.align_images.find_corners(image, filter_grayscale, num=10, gray_filter=20)[source]

Detect outer document corners via contours and min-area rectangles.

Parameters:
  • image – BGR numpy image.

  • filter_grayscale – If True, threshold grayscale before edge detection.

  • num – Number of largest contours to consider (increased recursively on failure).

  • gray_filter – Threshold value when filter_grayscale is True.

Returns:

(outer_corners, valid) where outer_corners are four (x, y) tuples and valid reflects validate_corners (may recurse with larger num).

formhtr.libs.processing.align_images.transform(scanned, template, scanned_points, template_points)[source]

Apply a homography mapping scan corners to template corners.

Parameters:
  • scanned – Source BGR image.

  • template – Target image defining output size.

  • scanned_points – Four scan corner coordinates.

  • template_points – Four template corner coordinates.

Returns:

Warped scanned with template dimensions.

formhtr.libs.processing.align_images.align_images(scanned, template, filter_grayscale)[source]

Align scanned to template using automatically detected corners.

Parameters:
  • scanned – Scanned page BGR image.

  • template – Template BGR image.

  • filter_grayscale – Passed to find_corners for the scan and template.

Returns:

Warped scan, or None if corners are invalid for either image.

formhtr.libs.processing.align_images.format_point(point)[source]

Serialize a corner to JSON-friendly ints.

Parameters:

point(x, y) numeric pair.

Returns:

Dict with x and y keys.

formhtr.libs.processing.align_images.get_alignment_data(scanned, template)[source]

Compute template and scan corner sets for external alignment UIs.

Parameters:
  • scanned – Scanned BGR image.

  • template – Template BGR image.

Returns:

Dict with templatePoints and targetPoints lists of {"x","y"} dicts.

formhtr.libs.processing.barcode.extract_barcode(candidates)[source]

Pick a barcode string from per-service single-word OCR fallbacks.

Parameters:

candidates – Dict mapping provider name to a list of Rectangle (or empty).

Returns:

Most frequent barcode string among singleton lists, or None if none.

formhtr.libs.processing.barcode.read_barcode(image, candidates)[source]

Decode a barcode from a ROI image, with rotation retry and OCR fallback.

Parameters:
  • image – ROI crop as numpy BGR array.

  • candidates – Per-service OCR rectangles (used if decoders fail).

Returns:

Decoded payload string, or None if nothing is found.

formhtr.libs.processing.checkbox.is_ticked(image_array, edge_ignore_percentage=0.2, threshold_percentage=0.1)[source]

Detected whether checkbox is ticked

Parameters:
  • image_array (np.array) – given picture

  • edge_ignore_percentage (float, optional) – cutoff edges to avoid detecting box. Defaults to 0.2.

  • threshold_percentage (float, optional) – required amount of dark pixel. Defaults to 0.1.

Returns:

True if checkbox is ticked

Return type:

bool

formhtr.libs.processing.process_area.is_a_number(string)[source]

Polish given string and check if can be converted to float.

Parameters:

string (str) – given string possibly containing a float

Returns:

polished string

Return type:

str

formhtr.libs.processing.process_area.identify_number(values)[source]

If some number were found, give them priority

Otherwise we will handle the region is general text area

Parameters:

values (list) – list of identified values

Returns:

identified number (as string for compatibility)

Return type:

str

formhtr.libs.processing.process_area.separate_to_lines(rectangles)[source]

Split set of rectangles into lines.

This is determined by center of rectangle being inside of previous rectangle bounds.

Parameters:

rectangles (list) – given list of rectangles

Returns:

list of rectangles grouped to lines

Return type:

list of list

formhtr.libs.processing.process_area.get_max_dimensions(candidates)[source]

Identify dimensions of identified text used to determine its size

Parameters:

candidates (list) – identified lines of rectangles

Returns:

pair of values

Return type:

tuple

formhtr.libs.processing.process_area.align_pairwise(string_1, string_2)[source]

Align two strings

Parameters:
  • string_1 (str) – first string

  • string_2 (str) – second string

Returns:

aligned string

Return type:

str

formhtr.libs.processing.process_area.majority_vote(strings)[source]

Vote on individual positions of identified words

Parameters:

strings (list) – list of words (per service) corresponding to a line

Returns:

most probable list of words

Return type:

list

formhtr.libs.processing.process_area.remove_non_ascii(string)[source]

Remove non-ascii characters (these do not work in the alignment)

Parameters:

string (str) – input line

Returns:

line containing only ascii characters

Return type:

str

formhtr.libs.processing.process_area.identify_words(lines, is_number)[source]

Identify words from lines. Behaves differently based on how many lines there are.

Parameters:
  • lines (list) – given list of lines as strings

  • is_number (bool) – True if number(s) is/are expected

Returns:

identified word

Return type:

str

formhtr.libs.processing.process_area.filter_exceeding_words(lines, roi)[source]

Filter regions exceeding bounds of ROI

There are three cases: 1. None of the regions exceeds the bounds 2. Some of them 3. All of them

We keep everything as is in cases 1. and 3., in case 2. we filter out the exceeding ones (as at least one of the services thinks the exceeding part does not belong here)

Parameters:
  • lines (list) – given list of lines

  • roi (ROI) – respective ROI

Returns:

filtered lines

Return type:

list

formhtr.libs.processing.process_area.process_lines(lines, roi, is_number)[source]

Join lines to words let majority voting decide

Parameters:
  • lines (list) – lists of rectangles organised in lines

  • roi (ROI) – given ROI

  • is_number (bool) – True if number(s) is/are expected

formhtr.libs.processing.process_area.align_lines(candidate_lines)[source]

Group lines to categories by y-coordinate

Also sort them by y-coordinate to ensure correct order.

Parameters:

candidate_lines (list) – identified lines from all services

Returns:

lines grouped by y-coordinate

Return type:

list

formhtr.libs.processing.process_area.general_text_area(candidates, roi, is_number)[source]

Process text area

Parameters:
  • candidates (list of lists) – identified rectangles intersecting ROI

  • roi (ROI) – given ROI

  • is_number (bool) – True if number(s) is/are expected

Returns:

extracted text

Return type:

str

formhtr.libs.processing.read_content.process_content(indetified_content, logsheet_image, config, checkbox_edges)[source]

Fill each configured ROI using OCR unions, barcodes, or checkbox heuristics.

Parameters:
  • indetified_content – Dict google / amazon / azure -> word lists or None.

  • logsheet_image – Full-page aligned image as numpy array.

  • configLogsheetConfig with regions and residuals.

  • checkbox_edges – Fraction of ROI border to ignore when scoring checkbox ink.

Returns:

(results, artefacts) where results is a list of [varname, content_dict, fragment] and artefacts maps each service to leftover OCR snippets not assigned to ROIs.

formhtr.libs.processing.store_results.order_results(values)[source]

Collect non-empty per-provider values in column order.

Parameters:

values – Dict with optional keys inferred, google, amazon, azure.

Returns:

List of truthy values in fixed key order.

formhtr.libs.processing.store_results.write_header(worksheet)[source]

Write the main metadata sheet column titles.

Parameters:

worksheetxlsxwriter worksheet for the Metadata tab.

Returns:

None.

formhtr.libs.processing.store_results.store_image(image, location, index)[source]

Temporarily store image

Parameters:
  • image (Image) – image to be stored

  • location (str) – directory where to store the image

  • index (int) – unique identifier of the image

Returns:

Absolute path string of the written PNG file.

formhtr.libs.processing.store_results.store_results(results, artefacts, output_file, include_validation=False)[source]

Write ROI results and artefact crops into an XLSX workbook.

Parameters:
  • results – List of [varname, value_dict, crop_numpy] rows.

  • artefacts – Dict mapping service name to [text, crop_numpy] lists.

  • output_file – Path to the .xlsx file to create.

  • include_validation – If True, add Excel data validation where applicable.

Returns:

None. Temporary PNG crops next to output_file are removed after close.

formhtr.libs.processing.store_results.store_results_csv(results, artefacts, output_file)[source]

Write variable names and inferred values to UTF-8 CSV (no images).

Parameters:
  • results – List of [varname, value_dict, crop] (crop ignored).

  • artefacts – Unused; kept for API symmetry with store_results.

  • output_file – Path to the .csv file to create.

Returns:

None.