- 后端
- AI 应用
- NLP
【免费下载链接】xberg
Polyglot document intelligence with a Rust core: extract text, metadata, images, tables, and structured data from 106 formats across 140 file extensions, plus code intelligence for 371 languages. Fifteen bindings, with CLI, REST API, and MCP server.
本篇指南聚焦 Xberg 的 Elixir 绑定在图片 OCR 场景下的最小可运行方案:以fixtures/images/test_hello_world.png为样例输入,通过Xberg.ExtractInput构造 bytes 类型的提取请求,调用Xberg.extract_async/2触发 Rust 核心中的 OCR 管线,并从返回结果中取出识别文本。读完本文,你将掌握 Elixir 环境下图片 OCR 的完整调用链、ExtractInput各字段的语义、OCR 配置(含 Tesseract 引擎参数与多语言)的写法,以及如何用仓库自带的 e2e 测试验证提取结果。
场景:一个"带 OCR 的 PNG 提取"冒烟用例
仓库中docs-site/src/snippets-generated/elixir/smoke/ocr_image_png.md定义了一个标准的 smoke fixture:OCR: PNG image extraction with OCR enabled(OCR 开启状态下的 PNG 图片提取)。它的目标非常明确——验证 Elixir 绑定能够:
- 接收 PNG 图片的原始字节(而不是文件路径或 URI);
- 触发底层 OCR 引擎识别图片中的文字;
- 返回可被上层代码直接消费的提取结果(
results[0].content)。
该 fixture 的输入数据定义在 fixtures/smoke/ocr_image_png.json 中:call为extract,kind为bytes,字节内容正是 fixtures/images/test_hello_world.png(200x60 像素的 PNG 小图,画面即 "Hello, World!" 字样)。这意味着这是一个无外部依赖、可离线运行的自包含用例——不需要服务器、不需要网络,很适合作为 OCR 功能的入门冒烟测试。
环境准备:在 mix 项目中接入 xberg 依赖
OCR 能力来自同一套 Rust 实现核心,Elixir 侧通过 Rustler NIF 封装。按 packages/elixir/README.md 的说明,在mix.exs中加入依赖:
def deps do [ {:xberg, "~> 1.3.0"} ] end安装后即可获得完整的Xberg模块。该模块的公开 API 由 alef 自动生成(见 packages/elixir/lib/xberg.ex 顶部的 "auto-generated by alef" 标注),其中与本场景直接相关的两个入口是:
Xberg.extract(opts \\ [])—— 接收 keyword list,内部把:input与:config序列化为 JSON 后转发给 NIF;Xberg.extract_async(input_value, config)—— 直接接收ExtractInput结构体与 JSON 字符串配置(fixture 中使用的形式)。
最小调用示例:从 PNG 字节到识别文本
fixture 原文给出的 Elixir 示例即是最小可运行版本:
input_value = %Xberg.ExtractInput{bytes: :binary.bin_to_list(File.read!("images/test_hello_world.png")), config: %{}, filename: "test_hello_world.png", kind: "bytes", mime_type: "image/png"} result = Xberg.extract_async(input_value, "{}") IO.inspect(Enum.at(result.results, 0).content)逐行拆解,便于理解每个字段为什么必须这样写:
File.read!("images/test_hello_world.png")以二进制形式读入图片;:binary.bin_to_list/1把二进制转为整数列表——NIF 边界上 bytes 参数以整数列表传递,这正是 WASM 场景下Uint8Arraybridge 参数的对应物;%Xberg.ExtractInput{...}构造统一提取输入,其字段语义见 packages/elixir/lib/xberg/extract_input.ex:kind: "bytes":声明输入为原始字节(另一选项是"uri");bytes::PNG 的字节列表;mime_type: "image/png":显式告知核心按图片格式处理;filename: "test_hello_world.png":保留原始文件名,供格式嗅探与元数据使用;config: %{}:结构体层面的空配置;
Xberg.extract_async(input_value, "{}"):第二参数是 JSON 字符串形式的配置,"{}"表示全部使用默认配置——注意默认配置下OCR 是开启的,因此空配置即可触发识别;Enum.at(result.results, 0).content:结果集(results列表)中第一个条目的content字段即提取出的 Markdown 文本。
值得说明的是:Xberg.ExtractInput实现了Jason.Encoder,且序列化时会剔除值为nil的字段(见 extract_input.ex),所以未使用的字段不会污染请求;同时kind的默认值是:uri,构造 bytes 输入时必须显式传kind: "bytes",否则核心会按 URI 分支处理。
用仓库 e2e 测试验证"识别到了 Hello World"
fixture 并非孤立的文档示例,它在仓库的 e2e 测试套件中有完全对应的落地实现。打开 e2e/elixir/test/smoke_test.exs 可以看到ocr_image_png测试用例:
describe "ocr_image_png" do test "ocr_image_png" do input_value = %Xberg.ExtractInput{ bytes: :binary.bin_to_list(File.read!("images/test_hello_world.png")), config: %{}, filename: "test_hello_world.png", kind: "bytes", mime_type: "image/png" } {:ok, result} = Xberg.extract(input: input_value, config: "{}") assert Enum.at(result.results, 0).mime_type == "image/png" assert (is_binary(Enum.at(result.results, 0).content) && byte_size(Enum.at(result.results, 0).content) >= 1) || (is_list(Enum.at(result.results, 0).content) && length(Enum.at(result.results, 0).content) >= 1) assert Enum.any?(["Hello", "World", "hello", "world"], fn v -> String.contains?(to_string(Enum.at(result.results, 0).content), v) end) end end这段测试给出了三个可复用的断言范式,回答了"OCR 到底成没成功"这一核心问题:
| 断言目标 | 写法 | 含义 |
|---|---|---|
| 格式回显 | result.results[0].mime_type == "image/png" | 提取结果正确标注来源格式 |
| 非空产出 | content为 binary 且byte_size >= 1,或为 list 且length >= 1 | OCR 管线确实产出了文本(而非空文档) |
| 语义正确 | content包含"Hello"/"World"等关键词之一 | 识别出的文字内容与图片画面一致 |
前两条是通用冒烟标准,第三条直接验证识别质量——test_hello_world.png上印刷的就是 "Hello, World!",OCR 结果必须命中这些词。这意味着读者完全可以照抄这套断言,把它改造成自己图片 OCR 流水线的最小验收测试。
深入 OCR 配置:Tesseract 引擎参数与多语言
fixture 用"{}"走默认配置,但生产场景往往需要显式控制 OCR 行为。仓库中 docs-site/src/snippets-generated/elixir/ocr/ocr_multi_language.md 给出了开启多语言的配置写法:
input_value = %Xberg.ExtractInput{kind: "uri", mime_type: "image/png", uri: "https://example.com/images/test_hello_world.png"} result = Xberg.extract_async(input_value, "{\"ocr\":{\"backend\":\"tesseract\",\"enabled\":true,\"language\":[\"eng\",\"deu\",\"fra\"]}}") IO.inspect(Enum.at(result.results, 0).content)配置项逐项解读:
"ocr":OCR 功能段,enabled: true显式开启(默认即开启);"backend": "tesseract":指定引擎后端。仓库支持的 OCR 选项在 packages/elixir/README.md 中列明:Tesseract、PaddleOCR、Candle(支持的构建下)、通过 liter-llm 的 VLM OCR,以及插件钩子注册的自定义后端;"language": ["eng", "deu", "fra"]:多语言代码列表,Tesseract 内部会以+连接为eng+deu+fra交给引擎。
如果你需要更细粒度的引擎控制,Rust 侧公开的TesseractConfig结构(定义于 crates/xberg/src/types/formats.rs)暴露了完整参数面,它们同样可以通过"ocr"配置段的 JSON 传入:
| 字段 | 默认值 | 说明 |
|---|---|---|
language | ["eng"] | 识别语言代码列表;配置文件中也可接受单个字符串(如"eng+deu") |
psm | None(由管线按上下文选择) | 页面分割模式 1–13:3全自动分割、6单一文本块、11稀疏文本无顺序。0(OSD_ONLY)被拒绝,因为只做方向/文字检测而不产生识别结果 |
output_format | "markdown" | 输出"text"或"markdown" |
oem | 3 | OCR 引擎模式:0仅 Legacy、1仅 LSTM 神经网络、2两者、3默认 |
min_confidence | 0.0 | 最低置信度阈值(0.0–100.0),低于该值的词可能被剔除或标记 |
enable_table_detection | true | 自动表格检测与重建开关 |
use_cache | true | OCR 结果缓存开关(见 crates/xberg/src/ocr/cache.rs 的OcrCache实现) |
preprocessing | None | 图像预处理配置,对扫描件/低质量图片有明显收益 |
一个实际可用的显式配置示例(单语言、Markdown 输出、稀疏文本模式):
config_json = Jason.encode!(%{ "ocr" => %{ "backend" => "tesseract", "enabled" => true, "language" => ["eng"], "tesseract_config" => %{ "psm" => 11, "output_format" => "markdown", "oem" => 1 } } }) input_value = %Xberg.ExtractInput{ bytes: :binary.bin_to_list(File.read!("images/test_hello_world.png")), kind: "bytes", mime_type: "image/png", filename: "test_hello_world.png" } {:ok, result} = Xberg.extract(input: input_value, config: config_json) IO.inspect(Enum.at(result.results, 0).content)底层原理:一次 PNG OCR 请求的 Rust 调用链
从源码结构看,Elixir 侧的Xberg.extract_async/2只是 NIF 边界(Xberg.Native.extract_async),真正的 OCR 逻辑全部在 Rust 核心中完成。梳理 crates/xberg/src/ocr 目录可以还原这条调用链:
- 输入归一化:核心把
kind: "bytes"+mime_type: "image/png"的输入路由到图片提取器(extractors::image),图片不属于 PDF 等可内嵌 OCR 的复合格式,因此走独立图片 OCR分支; - 处理器入口:
OcrProcessor(crates/xberg/src/ocr/processor/mod.rs)暴露process_image/process_image_with_format/process_image_file等方法族,负责把图像字节交给具体后端; - 后端实现:以 Tesseract 为例,
TesseractBackend::process_image(&self, image_bytes: &[u8], config: &OcrConfig)(crates/xberg/src/ocr/tesseract_backend.rs)是引擎级实现;WASM 环境则对应tesseract_wasm_backend.rs的同名方法(crates/xberg/src/ocr/tesseract_wasm_backend.rs); - 缓存与批处理:
execution.rs中的process_image_with_cache/process_image_files_batch(crates/xberg/src/ocr/processor/execution.rs)在带缓存与批量场景下组织执行——这解释了use_cache配置项为何存在; - 结果落点:OCR 产出转换为
ExtractedDocument,进而映射为返回结构中的results[0],其content、mime_type等字段正是 Elixir 侧断言读取的位置(相关类型见 crates/xberg/src/types/formats.rs 的OcrExtractionResult)。
这条链路同时解释了 fixture 描述中"WASM 下锻炼Uint8Arraybridge 参数与生成的OcrBackendbridge 中 Promise await"的由来:bytes 在 Rust/Elixir 边界表现为整数列表,在 Rust/WASM 边界表现为Uint8Array;而生成的OcrBackendbridge(对应 packages/elixir/lib/xberg.ex 中Xberg.OcrBackend.Host的process_image(binary(), map())回调)在 WASM 端需要以异步 Promise 方式等待识别完成。因此这个看似简单的 smoke fixture,实际上横跨了三种运行时(BEAM、原生、WASM)的桥接路径。
结果消费:content 与其他可用字段
提取完成后,result.results是一个列表,本用例固定只有一个元素(单张图片输入),但保持Enum.at(result.results, 0)的索引写法可以在将来扩展到批量输入时无缝兼容。results[0]上至少可以直接读取:
content—— OCR 识别出的文本(默认以 Markdown 呈现);mime_type—— 来源格式(测试中用于断言"image/png");- 由
OcrExtractionResult携带的其余结构化信息(如表格结果OcrTable、置信度相关元数据,见 crates/xberg/src/types/formats.rs)。
Xberg.extract/1返回{:ok, map()} | {:error, atom, String.t()}(见 xberg.ex 的类型规格),生产代码建议用模式匹配处理错误分支,而不是像 smoke fixture 那样直接取字段。
小结与延伸
从一份不足 20 行的 fixture 出发,我们完整走通了 Xberg Elixir 图片 OCR 的全链路:ExtractInput的 bytes 构造 →extract/extract_async调用 → Rust 核心的OcrProcessor→ Tesseract 后端识别 →results[0].content消费,并用 e2e/elixir/test/smoke_test.exs 的断言范式验证了输出质量。想继续深入,可以沿着两条路径展开:一是把"{}"换成带tesseract_config的多语言/预处理配置,针对扫描件、表格、低分辨率图片调优(配置参考 crates/xberg/src/types/formats.rs);二是对照 docs-site/src/snippets-generated/elixir/ocr 目录下的ocr_force_all_pages、ocr_multi_language、ocr_paddle_backend、vlm_ocr等兄弟 fixture,探索 PDF 整页 OCR、PaddleOCR 与 VLM OCR 后端等更多能力。
- 后端
- AI 应用
- NLP
【免费下载链接】xberg
Polyglot document intelligence with a Rust core: extract text, metadata, images, tables, and structured data from 106 formats across 140 file extensions, plus code intelligence for 371 languages. Fifteen bindings, with CLI, REST API, and MCP server.
相关推荐
Xberg C 绑定基础 OCR 配置实战:用 Tesseract 从 PNG 图片提取文本
Xberg C 绑定基础 OCR 配置实战:用 Tesseract 从 PNG 图片提取文本 本篇技术指南聚焦 Xberg 文档智能库在 C 绑定(Xberg.
后端AI 应用NLPxberg C FFI 实战:用 C 语言对 PNG 图片执行 OCR 提取的完整流程
xberg C FFI 实战:用 C 语言对 PNG 图片执行 OCR 提取的完整流程 xberg 是一个以 Rust 为核心的多语言文档智能引擎,其 C FF
后端AI 应用NLPXberg Dart 绑定 OCR 实战:从 PNG 图片提取文本的完整调用链解析
Xberg Dart 绑定 OCR 实战:从 PNG 图片提取文本的完整调用链解析 本文以 Xberg 仓库中的 Dart 语言 OCR 冒烟样例( docs
后端AI 应用NLP
创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考