Documentation Index Fetch the complete documentation index at: https://mintlify.com/ragaeeb/kokokor/llms.txt
Use this file to discover all available pages before exploring further.
Overview
Layout elements are structural components detected in documents that help Kokokor better understand the document’s organization. Kokokor supports two types of layout elements:
Horizontal Lines - Used for footnote boundary detection
Rectangles - Used for heading and boxed content detection
Horizontal lines in documents often serve as visual separators between main content and footnotes. Kokokor uses these lines to automatically classify text below them as footnotes.
How It Works
Kokokor identifies the last horizontal line that isn’t contained within a rectangle, and marks all text below this line as footnotes. This helps in:
Separating main content from supplementary information
Proper document structure reconstruction
Academic and formal document processing
Basic Usage
import { reconstructParagraphs } from 'kokokor' ;
const horizontalLines = [
{ x: 100 , y: 2800 , width: 600 , height: 2 }, // Footer separator line
];
const result = reconstructParagraphs ({
observations: ocrObservations ,
page: pageContext ,
layout: {
horizontalLines
}
});
// Check for footnotes
result . paragraphs . forEach ( para => {
if ( para . isFootnote ) {
console . log ( 'Footnote:' , para . text );
}
});
Finding the Last Horizontal Line
Kokokor automatically finds the last horizontal separator for footnote detection:
const rectangles = [ /* detected rectangles */ ];
const horizontalLines = [ /* detected horizontal lines */ ];
Array of rectangle bounding boxes to exclude from horizontal line consideration
Array of horizontal line bounding boxes to analyze
Pixel tolerance for containment checking and filtering lines near the top edge
Rectangles for Heading Detection
Rectangles (boxes) in documents often highlight important content like headings, titles, or callouts. Kokokor automatically classifies text within rectangles as headings.
How It Works
Kokokor checks if text bounding boxes are contained within detected rectangles (with tolerance). Text inside rectangles receives the isHeading flag and gets special formatting:
Headings are followed by blank lines in formatted output
Helps with document outline generation
Assists in hierarchical content structuring
Basic Usage
import { reconstructParagraphs } from 'kokokor' ;
const rectangles = [
{ x: 200 , y: 100 , width: 400 , height: 50 }, // Title box
{ x: 150 , y: 500 , width: 500 , height: 40 }, // Section heading box
];
const result = reconstructParagraphs ({
observations: ocrObservations ,
page: pageContext ,
layout: {
rectangles
}
});
// Check for headings
result . paragraphs . forEach ( para => {
if ( para . isHeading ) {
console . log ( 'Heading:' , para . text );
}
});
Checking Containment
Use the isBoundingBoxContained utility (internal to layout.ts) logic to check if text is within a rectangle:
// This is done automatically by Kokokor
// Text bbox is considered contained if it's within the rectangle + tolerance
const isContained = isBoundingBoxContained (
textBbox ,
rectangleBbox ,
5 // tolerance in pixels
);
Filtering Horizontal Lines
Sometimes horizontal lines appear inside rectangles (like underlined headings). Kokokor provides filterHorizontalLinesOutsideRectangles to remove these:
import { filterHorizontalLinesOutsideRectangles } from 'kokokor' ;
const rectangles = [
{ x: 100 , y: 100 , width: 600 , height: 80 }, // Heading box
];
const allHorizontalLines = [
{ x: 120 , y: 170 , width: 560 , height: 2 }, // Line inside heading (underline)
{ x: 100 , y: 2800 , width: 600 , height: 2 }, // Footer separator
];
// Filter out lines inside rectangles
const relevantLines = filterHorizontalLinesOutsideRectangles (
rectangles ,
allHorizontalLines ,
5 // pixel tolerance
);
// Result: Only the footer separator remains
console . log ( relevantLines . length ); // 1
Array of rectangles to check against
Array of horizontal lines to filter
Pixel tolerance for boundary checking. Extends rectangle boundaries to catch lines that are slightly outside due to OCR inaccuracies.
Array of horizontal lines that are NOT contained within any rectangle
Complete Example
Here’s a complete example using both layout elements:
import {
reconstructParagraphs ,
filterHorizontalLinesOutsideRectangles ,
calculateDPI
} from 'kokokor' ;
// Layout elements detected from document
const allRectangles = [
{ x: 200 , y: 50 , width: 400 , height: 60 }, // Title box
{ x: 150 , y: 500 , width: 500 , height: 40 }, // Section heading
];
const allHorizontalLines = [
{ x: 220 , y: 105 , width: 360 , height: 2 }, // Underline in title
{ x: 100 , y: 2800 , width: 600 , height: 2 }, // Footer separator
];
// Filter out horizontal lines that are inside rectangles
const relevantHorizontalLines = filterHorizontalLinesOutsideRectangles (
allRectangles ,
allHorizontalLines ,
5 // tolerance
);
console . log ( `Found ${ relevantHorizontalLines . length } relevant horizontal lines` );
// Calculate DPI if you have image and PDF dimensions
const dpi = calculateDPI (
{ width: 2480 , height: 3508 }, // Image size
{ width: 595 , height: 842 } // PDF size (A4)
);
// Reconstruct paragraphs with layout elements
const result = reconstructParagraphs (
{
observations: ocrObservations ,
page: {
width: 2480 ,
height: 3508 ,
dpiX: dpi . x ,
dpiY: dpi . y ,
},
layout: {
rectangles: allRectangles ,
horizontalLines: relevantHorizontalLines ,
},
}
);
// Analyze results
console . log ( ' \n Document Structure:' );
result . paragraphs . forEach (( para , i ) => {
if ( para . isHeading ) {
console . log ( ` \n === ${ para . text } ===` );
} else if ( para . isFootnote ) {
console . log ( ` [Footnote] ${ para . text } ` );
} else {
console . log ( ` ${ para . text } ` );
}
});
Working with Detection Libraries
Many OCR and layout detection libraries can provide rectangle and line information:
From Surya Layout Detection
import { mapMatrixToBoundingBox } from 'kokokor' ;
// Surya layout results
const suryaLayout = {
bboxes: [
{ bbox: [ 200 , 50 , 600 , 110 ], label: 'heading' },
{ bbox: [ 100 , 2800 , 700 , 2802 ], label: 'line' },
],
};
// Convert to Kokokor format
const rectangles = suryaLayout . bboxes
. filter ( item => item . label === 'heading' )
. map ( item => mapMatrixToBoundingBox ( item . bbox as [ number , number , number , number ]));
const horizontalLines = suryaLayout . bboxes
. filter ( item => item . label === 'line' )
. map ( item => mapMatrixToBoundingBox ( item . bbox as [ number , number , number , number ]));
From Custom Detection
// Your custom layout detection function
function detectLayoutElements ( imagePath : string ) {
// ... your detection logic ...
return {
rectangles: [
// Detected boxes/frames
{ x: 200 , y: 50 , width: 400 , height: 60 },
],
horizontalLines: [
// Detected horizontal separators
{ x: 100 , y: 2800 , width: 600 , height: 2 },
],
};
}
const layout = detectLayoutElements ( './document.png' );
const result = reconstructParagraphs ({
observations: ocrObservations ,
page: pageContext ,
layout ,
});
Tolerance Settings
The tolerance parameter controls how strictly containment is checked:
Strict Containment
Lenient Containment
// Tolerance = 0: Exact containment required
const lines = filterHorizontalLinesOutsideRectangles (
rectangles ,
horizontalLines ,
0 // no tolerance
);
Use tolerance values between 5-10 pixels to account for OCR and layout detection inaccuracies. This helps catch lines and text that are slightly misaligned due to scanning artifacts.
Common Patterns
Academic Papers
// Academic papers often have:
// - Title in a box at the top
// - Horizontal line before references/footnotes
const academicLayout = {
rectangles: [
{ x: 200 , y: 100 , width: 400 , height: 80 }, // Title
],
horizontalLines: [
{ x: 100 , y: 2600 , width: 600 , height: 1 }, // References separator
],
};
Books and Reports
// Books may have:
// - Chapter headings in boxes
// - Multiple horizontal lines for sections
const bookLayout = {
rectangles: [
{ x: 150 , y: 200 , width: 500 , height: 50 }, // Chapter title
{ x: 150 , y: 1500 , width: 500 , height: 40 }, // Section heading
],
horizontalLines: [
{ x: 100 , y: 3000 , width: 600 , height: 2 }, // Footer line
],
};
Next Steps
Advanced Configuration Explore all configuration options
Surya Integration Convert Surya layout detection results