Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
69 commits
Select commit Hold shift + click to select a range
2373fa3
wip: perf reporting automation and integration test updates
tobi-legan Mar 19, 2026
a2c5d0c
feat: add clinical chemistry quality test with dedicated ground truth
tobi-legan Mar 23, 2026
df2cb0a
feat: enhance performance reporting for mobile integration tests
tobi-legan Apr 10, 2026
539b177
Merge remote-tracking branch 'origin/main' into feat/perf-reporting-a…
tobi-legan Apr 11, 2026
0d3f811
feat: add liver function test image and regenerate mobile test runners
tobi-legan Apr 11, 2026
3a2e21c
fix: re-authenticate AWS OIDC before Device Farm log download
tobi-legan Apr 11, 2026
def114d
chore: remove unnecessary OIDC re-auth before log download
tobi-legan Apr 11, 2026
6264553
fix: resolve standardjs lint errors in OCR integration tests
tobi-legan Apr 11, 2026
a28fa38
feat: add CPU/GPU variants to OCR medical image tests
tobi-legan Apr 11, 2026
4899b34
fix: resolve mobile bundling failure and desktop test issues
tobi-legan Apr 11, 2026
a957dfc
fix: expand expected words for OCR medical document tests
tobi-legan Apr 11, 2026
ae174b9
fix: resolve desktop artifact collision and Android AAPT2 build failure
tobi-legan Apr 11, 2026
e3ad898
fix: enable performance reporting on mobile Device Farm runs
tobi-legan Apr 13, 2026
0a397fb
fix: graceful DocTR model download failure on mobile
tobi-legan Apr 13, 2026
58c3c37
fix: download device logcat from Device Farm for perf report extraction
tobi-legan Apr 13, 2026
78d6a96
fix: capture device logs via Appium getLogs for perf report extraction
tobi-legan Apr 13, 2026
75152c0
fix: use Appium pullFile for mobile perf report extraction
tobi-legan Apr 13, 2026
b69ebae
fix: prevent false positive perf marker extraction from wdio config
tobi-legan Apr 13, 2026
7dee020
fix: call writeReport() after each test on mobile, not just on exit
tobi-legan Apr 13, 2026
3dddcde
fix: resolve incomplete mobile perf report (truncation, permissions, …
tobi-legan Apr 13, 2026
ace9864
fix: sanitize logcat control chars and fix run-as extraction on Devic…
tobi-legan Apr 13, 2026
56a786f
fix: write per-device performance reports with actual device model names
tobi-legan Apr 13, 2026
56ad6a4
feat: enable quality metrics (CER/WER/keyword/KV) on mobile reports
tobi-legan Apr 13, 2026
f4381b7
fix: multi-device HTML generation, artifact upload, and run_number in…
tobi-legan Apr 13, 2026
778903b
feat: split mobile OCR tests into perf + regular Device Farm runs
tobi-legan Apr 13, 2026
3a52ffd
fix: aggressive control char sanitization + filter perf results at ex…
tobi-legan Apr 14, 2026
685cd57
fix: show individual iteration columns and fix mobile quality metrics
tobi-legan Apr 14, 2026
530b281
fix: resolve Android perf report extraction failures
tobi-legan Apr 14, 2026
f6bdc7b
fix: write perf report to file instead of console.log to avoid interl…
tobi-legan Apr 14, 2026
57292a2
fix: correct lab_results ground truth and add quality verification to…
tobi-legan Apr 14, 2026
43a342c
fix: make keyword and KV matching order-independent for multi-word ph…
tobi-legan Apr 14, 2026
aef1e53
fix: add detailed KV mismatch table to HTML quality diagnostics
tobi-legan Apr 14, 2026
36d8258
feat: add quality metrics methodology section to HTML report
tobi-legan Apr 14, 2026
6a70d63
fix: Android perf report extraction failures
tobi-legan Apr 14, 2026
dde353f
feat: add Word Recognition Rate metric alongside CER/WER
tobi-legan Apr 14, 2026
a6f0d1f
feat: embed test images in HTML report, add CI step summary, fix clin…
tobi-legan Apr 14, 2026
02b20f6
fix: limit perf report to medical image tests only, improve image lig…
tobi-legan Apr 14, 2026
35209d1
fix: overhaul Android perf report extraction with 4-strategy approach
tobi-legan Apr 14, 2026
3d4546f
fix: split WDIO config into separate step to fix GH Actions expressio…
tobi-legan Apr 14, 2026
34a2000
fix: replace sed -i with portable sed + mv for macOS compatibility
tobi-legan Apr 14, 2026
6c45c67
fix: add Device Farm log diagnostics and upload raw artifacts
tobi-legan Apr 14, 2026
9eb9a16
fix: Android perf report extraction — search logcat and download cust…
tobi-legan Apr 14, 2026
5a980f6
fix: rewrite WDIO after hook with 3 extraction strategies for Android
tobi-legan Apr 14, 2026
1c667fb
fix: broken artifact download (spaces in name) and macOS bash syntax
tobi-legan Apr 14, 2026
5a87954
fix: parse Android perf reports from logcat with interleaved content
tobi-legan Apr 14, 2026
f15cebb
fix: chunk large perf reports to avoid Android logcat truncation
tobi-legan Apr 14, 2026
4a5969f
fix: robust Android chunked perf report extraction
tobi-legan Apr 14, 2026
af116f6
fix: fallback to repo test images when device paths unavailable
tobi-legan Apr 14, 2026
f8fa4b1
fix: write perf report to console once at exit instead of per iteration
tobi-legan Apr 14, 2026
3866557
fix: use lightweight per-iteration perf writes to avoid logcat buffer…
tobi-legan Apr 14, 2026
7fbc04a
fix: poll results file for stability before extracting perf report
tobi-legan Apr 14, 2026
8c5eabe
fix: include image_path in writeToConsole output for Android reports
tobi-legan Apr 14, 2026
8193d29
fix: write full quality at checkpoints and bail poll early on Android
tobi-legan Apr 14, 2026
797a1a9
fix: use mobile:shell for stability poll and direct file extraction
tobi-legan Apr 14, 2026
fee59cc
feat: combined perf report across all platforms + unified summary table
tobi-legan Apr 15, 2026
d73bd5f
chore: remove per-platform summaries, use combined report only
tobi-legan Apr 15, 2026
cb4e91e
fix: increase stability threshold to 30s to avoid premature poll exit
tobi-legan Apr 15, 2026
1075fd9
feat: combined report includes desktop + mobile, all platforms in one…
tobi-legan Apr 15, 2026
f13998b
fix: add /tmp/ to poll paths and remove premature bail-out
tobi-legan Apr 15, 2026
85a1d5f
fix: add external storage paths for Pixel perf report extraction
tobi-legan Apr 15, 2026
385dbe3
fix: add safety nets for Pixel perf report extraction
tobi-legan Apr 15, 2026
9299d4d
feat: per-device HTML reports, cleaner summary, remove PR comments
tobi-legan Apr 15, 2026
ae7e912
fix: use echo instead of printf in summary to avoid format string errors
tobi-legan Apr 15, 2026
9a76e3e
chore: remove per-platform step summaries from desktop workflow
tobi-legan Apr 15, 2026
5dd1b09
fix: remove per-device step summary from desktop test runner
tobi-legan Apr 16, 2026
4fbe9db
doc: clarify why DocTR URLs are included in presigned URL script
tobi-legan Apr 16, 2026
177c594
fix: address CodeQL regex injection and remove unused variables
tobi-legan Apr 16, 2026
715cf41
fix: use filter pattern as regex first, escape only on invalid syntax
tobi-legan Apr 16, 2026
f02a7a6
fix: replace regex filter with substring matching to resolve CodeQL a…
tobi-legan Apr 16, 2026
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
704 changes: 530 additions & 174 deletions .github/workflows/integration-mobile-test-ocr-onnx.yml

Large diffs are not rendered by default.

30 changes: 30 additions & 0 deletions .github/workflows/integration-test-ocr-onnx.yml
Original file line number Diff line number Diff line change
Expand Up @@ -166,3 +166,33 @@ jobs:
run: npm run test:integration
env:
QASE_API_TOKEN: ${{ secrets.QASE_API_TOKEN }}

- name: Generate HTML performance report
if: always()
working-directory: ${{ inputs.workdir || env.PKG_DIR }}
shell: bash
run: |
echo "Checking for performance report..."
ls -la test/results/ 2>/dev/null || echo "test/results/ directory not found"
if [ -f test/results/performance-report.json ]; then
echo "Found performance-report.json, generating HTML..."
node ../../scripts/perf-report/aggregate.js \
--dir test/results \
--output-html test/results/performance-report.html \
--output-json test/results/performance-summary.json \
--output test/results/performance-report.md
else
echo "performance-report.json not found — skipping HTML generation"
fi

- name: Upload performance report
if: always()
uses: actions/upload-artifact@v4
with:
name: perf-report-ocr-${{ matrix.os }}-${{ matrix.arch }}-${{ github.run_number }}
path: |
${{ inputs.workdir || env.PKG_DIR }}/test/results/performance-report.json
${{ inputs.workdir || env.PKG_DIR }}/test/results/performance-report.html
${{ inputs.workdir || env.PKG_DIR }}/test/results/performance-summary.json
retention-days: 90
if-no-files-found: ignore
Original file line number Diff line number Diff line change
Expand Up @@ -174,3 +174,12 @@ jobs:
env:
CHATTERBOX_VARIANT: ${{ matrix.variant }}
QASE_API_TOKEN: ${{ secrets.QASE_API_TOKEN }}

- name: Upload performance report
if: always()
uses: actions/upload-artifact@v4
with:
name: perf-report-tts-${{ matrix.platform }}-${{ matrix.arch }}-${{ matrix.variant }}-${{ github.run_number }}
path: ${{ inputs.workdir }}/test/results/performance-report.json
retention-days: 90
if-no-files-found: ignore
137 changes: 137 additions & 0 deletions .github/workflows/perf-report.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,137 @@
name: Performance Report

on:
schedule:
- cron: "0 9 * * 1" # Every Monday 9am UTC
workflow_dispatch:
inputs:
addon:
description: "Addon to generate report for"
type: choice
required: true
options:
- ocr-onnx
- nmtcpp
- llamacpp-llm
- onnx-tts
workflow_name:
description: "Integration test workflow name to query"
type: choice
required: true
options:
- "Integration Tests (OCR)"
- "Mobile Integration Tests (OCR)"
- "Integration Tests (NMTCPP)"
- "Integration Tests (LLM)"
- "Integration Tests (TTS)"
runs:
description: "Number of recent runs to aggregate"
type: number
required: false
default: 6

jobs:
generate-report:
runs-on: ubuntu-latest
permissions:
contents: read
actions: read

steps:
- name: Checkout code
uses: actions/checkout@v6

- name: Setup Node.js
uses: actions/setup-node@v6
with:
node-version: lts/*

- name: Generate performance report (manual)
if: ${{ github.event_name == 'workflow_dispatch' }}
env:
GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
run: |
node scripts/perf-report/aggregate.js \
--addon "${{ inputs.addon }}" \
--workflow "${{ inputs.workflow_name }}" \
--runs ${{ inputs.runs }} \
--output "reports/${{ inputs.addon }}-performance.md" \
--output-json "reports/${{ inputs.addon }}-performance.json" \
--output-html "reports/${{ inputs.addon }}-performance.html"

- name: Generate performance reports (scheduled - all addons)
if: ${{ github.event_name == 'schedule' }}
env:
GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
run: |
mkdir -p reports

echo "=== OCR (Desktop) ==="
node scripts/perf-report/aggregate.js \
--addon ocr-onnx \
--workflow "Integration Tests (OCR)" \
--runs 6 \
--output reports/ocr-onnx-performance.md \
--output-json reports/ocr-onnx-performance.json \
--output-html reports/ocr-onnx-performance.html || true

echo "=== OCR (Mobile) ==="
node scripts/perf-report/aggregate.js \
--addon ocr-onnx \
--workflow "Mobile Integration Tests (OCR)" \
--runs 6 \
--output reports/ocr-onnx-mobile-performance.md \
--output-json reports/ocr-onnx-mobile-performance.json \
--output-html reports/ocr-onnx-mobile-performance.html || true

echo "=== Translation ==="
node scripts/perf-report/aggregate.js \
--addon nmtcpp \
--workflow "Integration Tests (NMTCPP)" \
--runs 6 \
--output reports/nmtcpp-performance.md \
--output-json reports/nmtcpp-performance.json \
--output-html reports/nmtcpp-performance.html || true

echo "=== Vision/LLM ==="
node scripts/perf-report/aggregate.js \
--addon llamacpp-llm \
--workflow "Integration Tests (LLM)" \
--runs 6 \
--output reports/llamacpp-llm-performance.md \
--output-json reports/llamacpp-llm-performance.json \
--output-html reports/llamacpp-llm-performance.html || true

echo "=== TTS ==="
node scripts/perf-report/aggregate.js \
--addon onnx-tts \
--workflow "Integration Tests (TTS)" \
--runs 6 \
--output reports/onnx-tts-performance.md \
--output-json reports/onnx-tts-performance.json \
--output-html reports/onnx-tts-performance.html || true

- name: Write GitHub Step Summary
if: always()
run: |
echo "# Performance Reports" >> $GITHUB_STEP_SUMMARY
echo "" >> $GITHUB_STEP_SUMMARY
echo "Generated: $(date -u '+%Y-%m-%d %H:%M UTC')" >> $GITHUB_STEP_SUMMARY
echo "" >> $GITHUB_STEP_SUMMARY
for f in reports/*.md; do
if [ -f "$f" ]; then
cat "$f" >> $GITHUB_STEP_SUMMARY
echo "" >> $GITHUB_STEP_SUMMARY
echo "---" >> $GITHUB_STEP_SUMMARY
echo "" >> $GITHUB_STEP_SUMMARY
fi
done

- name: Upload reports
if: always()
uses: actions/upload-artifact@v4
with:
name: performance-reports-${{ github.run_number }}
path: reports/
retention-days: 90
if-no-files-found: ignore
8 changes: 8 additions & 0 deletions packages/ocr-onnx/scripts/generate-ocr-presigned-urls.sh
Original file line number Diff line number Diff line change
Expand Up @@ -79,6 +79,14 @@ for name in "${RECOGNIZERS[@]}"; do
url_escaped="${url//\"/\\\"}"
printf ' "%s": "%s",\n' "$key" "$url_escaped" >> "$JSON_FILE"
done
# DocTR models — direct GitHub release URLs (no S3 presigning needed, these are public).
# On mobile, _resolveDoctrUrl() in utils.js reads these from ocr-model-urls.json first,
# falling back to hardcoded GitHub URLs if missing. Kept here as override point in case
# GitHub releases are rate-limited on Device Farm.
printf ' "doctr_db_resnet50_url": "%s",\n' "https://github.com/felixdittrich92/OnnxTR/releases/download/v0.0.1/db_resnet50-69ba0015.onnx" >> "$JSON_FILE"
printf ' "doctr_parseq_url": "%s",\n' "https://github.com/felixdittrich92/OnnxTR/releases/download/v0.0.1/parseq-00b40714.onnx" >> "$JSON_FILE"
printf ' "doctr_db_mobilenet_v3_large_url": "%s",\n' "https://github.com/felixdittrich92/OnnxTR/releases/download/v0.2.0/db_mobilenet_v3_large-4987e7bd.onnx" >> "$JSON_FILE"
printf ' "doctr_crnn_mobilenet_v3_small_url": "%s",\n' "https://github.com/felixdittrich92/OnnxTR/releases/download/v0.0.1/crnn_mobilenet_v3_small-bded4d49.onnx" >> "$JSON_FILE"
printf ' "generatedAt": "%s"\n}\n' "$(date -u +%Y-%m-%dT%H:%M:%SZ)" >> "$JSON_FILE"

echo ""
Expand Down
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
8 changes: 4 additions & 4 deletions packages/ocr-onnx/test/integration/doctr-basic.test.js
Original file line number Diff line number Diff line change
Expand Up @@ -56,7 +56,7 @@ test('DocTR basic - BMP image', { timeout: TEST_TIMEOUT }, async function (t) {
// tilted/vertical vary by platform and DocTR lacks per-crop rotation handling (unlike EasyOCR).
t.ok(outputTexts.some(w => w.toLowerCase().includes('normal')), 'BMP should detect "normal"')
t.comment('BMP detected texts: ' + JSON.stringify(outputTexts))
t.comment(formatOCRPerformanceMetrics('[DocTR BMP]', stats, outputTexts))
t.comment(formatOCRPerformanceMetrics('[DocTR BMP]', stats, outputTexts, { skipReport: true }))
})

test('DocTR basic - JPEG image', { timeout: TEST_TIMEOUT }, async function (t) {
Expand All @@ -74,7 +74,7 @@ test('DocTR basic - JPEG image', { timeout: TEST_TIMEOUT }, async function (t) {
t.ok(results.length > 0, `JPEG: should detect text regions, got ${results.length}`)
t.ok(outputTexts.some(w => w.toLowerCase().includes('normal')), 'JPEG should detect "normal"')
t.comment('JPEG detected texts: ' + JSON.stringify(outputTexts))
t.comment(formatOCRPerformanceMetrics('[DocTR JPEG]', stats, outputTexts))
t.comment(formatOCRPerformanceMetrics('[DocTR JPEG]', stats, outputTexts, { skipReport: true }))
})

test('DocTR basic - PNG image', { timeout: TEST_TIMEOUT }, async function (t) {
Expand All @@ -92,7 +92,7 @@ test('DocTR basic - PNG image', { timeout: TEST_TIMEOUT }, async function (t) {
t.ok(results.length > 0, `PNG: should detect text regions, got ${results.length}`)
t.ok(outputTexts.some(w => w.toLowerCase().includes('normal')), 'PNG should detect "normal"')
t.comment('PNG detected texts: ' + JSON.stringify(outputTexts))
t.comment(formatOCRPerformanceMetrics('[DocTR PNG]', stats, outputTexts))
t.comment(formatOCRPerformanceMetrics('[DocTR PNG]', stats, outputTexts, { skipReport: true }))
})

test('DocTR basic - English image', { timeout: TEST_TIMEOUT }, async function (t) {
Expand Down Expand Up @@ -124,5 +124,5 @@ test('DocTR basic - English image', { timeout: TEST_TIMEOUT }, async function (t
t.ok(coordsInBounds, 'All bbox coordinates within image bounds (905x480)')

t.comment('English detected texts: ' + JSON.stringify(outputTexts))
t.comment(formatOCRPerformanceMetrics('[DocTR English]', stats, outputTexts))
t.comment(formatOCRPerformanceMetrics('[DocTR English]', stats, outputTexts, { skipReport: true }))
})
Original file line number Diff line number Diff line change
@@ -0,0 +1,72 @@
'use strict'

const test = require('brittle')
const { getImagePath, formatOCRPerformanceMetrics, runDoctrOCR, ensureDoctrModels } = require('./utils')

const DOCTR_TEST_TIMEOUT = 180 * 1000

let DB_MOBILENET
let CRNN_MOBILENET
let modelsAvailable = false

test('DocTR clinical chemistry - download models', { timeout: DOCTR_TEST_TIMEOUT }, async function (t) {
const models = await ensureDoctrModels(['db_mobilenet_v3_large.onnx', 'crnn_mobilenet_v3_small.onnx'])
if (!models) {
t.comment('DocTR models unavailable (download failed) — remaining tests will be skipped')
return
}
DB_MOBILENET = models.db_mobilenet_v3_large
CRNN_MOBILENET = models.crnn_mobilenet_v3_small
modelsAvailable = true
t.ok(DB_MOBILENET, 'db_mobilenet model available')
t.ok(CRNN_MOBILENET, 'crnn_mobilenet model available')
})

const PERF_RUNS = 3

const EXPECTED_WORDS = [
'clinical', 'chemistry', 'alkaline', 'phosphatase',
'hemoglobin', 'creatinine', 'cholesterol', 'triglycerides',
'bilirubin', 'albumin', 'protein', 'lipid'
]

function runClinicalChemistryTest (ep, run) {
const useGPU = ep === 'gpu'
const tag = ep.toUpperCase()

test(`DocTR clinical chemistry [${tag}] run ${run} - db_mobilenet + crnn_mobilenet`, { timeout: DOCTR_TEST_TIMEOUT }, async function (t) {
if (!modelsAvailable) { t.comment('Skipped — models unavailable'); return }
const imagePath = getImagePath('/test/images/clinical_chemistry.png')

t.comment(`Testing DocTR on clinical chemistry lab result image [${tag}] (run ${run}/${PERF_RUNS})`)
t.comment('Detector: db_mobilenet_v3_large, Recognizer: crnn_mobilenet_v3_small (CTC)')
t.comment('straightenPages: true, useGPU: ' + useGPU)

const { results, stats } = await runDoctrOCR(t, {
pathDetector: DB_MOBILENET,
pathRecognizer: CRNN_MOBILENET,
decodingMethod: 'ctc',
straightenPages: true,
useGPU
}, imagePath)

const texts = results.map(r => r.text)
t.comment('Detected texts: ' + JSON.stringify(texts))
t.comment(formatOCRPerformanceMetrics(`[DocTR clinical_chemistry] [${tag}]`, stats, texts, { imagePath }))

t.ok(results.length > 0, `should detect text regions, got ${results.length}`)

const lowerTexts = texts.map(w => w.toLowerCase())
for (const word of EXPECTED_WORDS) {
t.ok(
lowerTexts.some(w => w.includes(word)),
`should detect "${word}" in clinical chemistry report`
)
}

t.pass(`DocTR clinical chemistry [${tag}] run ${run} completed successfully`)
})
}

for (let i = 1; i <= PERF_RUNS; i++) runClinicalChemistryTest('cpu', i)
for (let i = 1; i <= PERF_RUNS; i++) runClinicalChemistryTest('gpu', i)
74 changes: 74 additions & 0 deletions packages/ocr-onnx/test/integration/doctr-ct-scan.test.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,74 @@
'use strict'

const test = require('brittle')
const { getImagePath, formatOCRPerformanceMetrics, runDoctrOCR, ensureDoctrModels } = require('./utils')

const DOCTR_TEST_TIMEOUT = 180 * 1000

let DB_MOBILENET
let CRNN_MOBILENET
let modelsAvailable = false

test('DocTR CT scan - download models', { timeout: DOCTR_TEST_TIMEOUT }, async function (t) {
const models = await ensureDoctrModels(['db_mobilenet_v3_large.onnx', 'crnn_mobilenet_v3_small.onnx'])
if (!models) {
t.comment('DocTR models unavailable (download failed) — remaining tests will be skipped')
return
}
DB_MOBILENET = models.db_mobilenet_v3_large
CRNN_MOBILENET = models.crnn_mobilenet_v3_small
modelsAvailable = true
t.ok(DB_MOBILENET, 'db_mobilenet model available')
t.ok(CRNN_MOBILENET, 'crnn_mobilenet model available')
})

const EXPECTED_WORDS = [
'diagnostic', 'imaging', 'computed', 'tomography',
'chest', 'abdomen', 'lung', 'liver', 'pancreas',
'gallbladder', 'spleen', 'radiologist', 'allied',
'medical', 'center', 'patient', 'heart', 'trachea',
'vascular', 'normal'
]

const PERF_RUNS = 3

function runCtScanTest (ep, run) {
const useGPU = ep === 'gpu'
const tag = ep.toUpperCase()

test(`DocTR CT scan [${tag}] run ${run} - db_mobilenet + crnn_mobilenet`, { timeout: DOCTR_TEST_TIMEOUT }, async function (t) {
if (!modelsAvailable) { t.comment('Skipped — models unavailable'); return }
const imagePath = getImagePath('/test/images/ct_scan_report.png')

t.comment(`Testing DocTR on CT scan diagnostic report image [${tag}] (run ${run}/${PERF_RUNS})`)
t.comment('Detector: db_mobilenet_v3_large, Recognizer: crnn_mobilenet_v3_small (CTC)')
t.comment('straightenPages: true, useGPU: ' + useGPU)

const { results, stats } = await runDoctrOCR(t, {
pathDetector: DB_MOBILENET,
pathRecognizer: CRNN_MOBILENET,
decodingMethod: 'ctc',
straightenPages: true,
useGPU
}, imagePath)

const texts = results.map(r => r.text)
t.comment('Detected texts: ' + JSON.stringify(texts))
t.comment(formatOCRPerformanceMetrics(`[DocTR ct_scan_report] [${tag}]`, stats, texts, { imagePath }))

t.ok(results.length > 0, `should detect text regions, got ${results.length}`)

const lowerTexts = texts.map(w => w.toLowerCase())
for (const word of EXPECTED_WORDS) {
t.ok(
lowerTexts.some(w => w.includes(word)),
`should detect "${word}" in CT scan report`
)
}

t.pass(`DocTR CT scan report [${tag}] run ${run} completed successfully`)
})
}

for (let i = 1; i <= PERF_RUNS; i++) runCtScanTest('cpu', i)
for (let i = 1; i <= PERF_RUNS; i++) runCtScanTest('gpu', i)
2 changes: 1 addition & 1 deletion packages/ocr-onnx/test/integration/doctr-french.test.js
Original file line number Diff line number Diff line change
Expand Up @@ -42,6 +42,6 @@ test('DocTR french test - accented characters', { timeout: TEST_TIMEOUT }, async
)
t.comment('Contains accented characters: ' + hasAccent)

t.comment(formatOCRPerformanceMetrics('[DocTR French]', stats, outputTexts))
t.comment(formatOCRPerformanceMetrics('[DocTR French]', stats, outputTexts, { skipReport: true }))
t.pass('DocTR French test completed successfully')
})
Loading
Loading