<!-- Source: https://deepseek-browser-use.io.nexus/11 -->

# Windows OCR：本地图片与页面文字识别

`ocr_image` 识别图片上的文字。默认走后端 Windows 的 `Windows.Media.Ocr`，**也可以配置成调用一条外部文档 OCR 命令**（见第 6 节）。它适用于扫描件、公告图片和页面中没有 DOM 文本的区域。它不是二维码解码器，也不等于文档结构化提取；图片中的表格、印章、手写字和模糊字符需要另外核对。

有 DOM 文本时优先使用 `get_browser_state`、`find_text` 或 `extract_markdown`，不必先截图再 OCR。**唯一的例外是「内容本身就是一张图」**：政府公告的附件、票据、明细表在页面里只是一个 `<img>`，文字一个都不在 DOM 里 —— 这时 OCR 才是第一条路，而且要先 `download_image` 拿到**原始文件**再识别（截屏再识别会掉字）。

## 1. 运行条件

- **默认后端（`windows`）要求运行浏览器服务的机器必须是 Windows**。客户端是 Windows、服务端是 Linux 时，不能使用这项内置 OCR；这时可以改用外部命令后端（第 6 节），它对操作系统没有这个限制。
- 代码通过系统自带的 Windows PowerShell 调用 WinRT，不要求另外安装云端 OCR SDK，也不把识别图片发送给云端识别服务。
- 需要系统有可用的 OCR 语言包，默认请求 `zh-Hans-CN`。识别英文可指定 `en-US`。
- 需要读取图片和创建临时文件的权限。网页元素识别还需要有效浏览器任务。

语言包可在 Windows「设置 → 时间和语言 → 语言和区域」中检查；相关可选功能名称通常为“光学字符识别”，具体入口随系统而异。

当前脚本先尝试请求语言，失败时会尝试用户配置的语言。**返回的 `language` 是请求语言，并不证明实际使用了该语言引擎**；当前实现没有返回 `engineLanguage`。遇到中文被识别成零散拉丁字母时，应检查语言包，不能据此判断原图内容。

## 2. 参数说明

统一入口为 `POST /playwright/command`，`method` 为 `ocr_image`。

| 参数 | 说明 |
| --- | --- |
| `id` | 外层任务 ID；页面元素截图需要有效任务 |
| `path` | 服务端本地图片文件路径，不是远程 URL；相对路径按服务进程工作目录解析。`download_image` 返回的 `path` 可直接填这里 |
| `index` | 当前页面快照中的元素索引 |
| `selector` | 图片或待识别区域的 CSS 选择器 |
| `frame` | 元素位于 iframe 时指定对应 frame |
| `language` | 可选，请求的识别语言；默认 `zh-Hans-CN` |

选择 `path` 或页面元素定位其中一种方式即可。如果同时传入非空 `path`，代码优先读取文件，不使用元素参数。页面索引必须来自最新快照，避免识别错图。

### 读取服务端图片

下面的路径和任务 ID 均为示例，应替换为实际值：

```json
{
  "id":"1001",
  "method":"ocr_image",
  "params":{
    "path":"tmp/sample-notice.png",
    "language":"zh-Hans-CN"
  }
}
```

文件路径分支本身不需要截图浏览器；页面元素分支必须先启动任务。远程调用时，本机文件需要先按[文件上传说明](<https://deepseek-browser-use.io.nexus/09>)放到服务端，不能把客户端磁盘路径当成服务端路径。

### 读取页面区域

```json
{
  "id":"1001",
  "method":"ocr_image",
  "params":{
    "selector":"#notice-image",
    "language":"zh-Hans-CN"
  }
}
```

服务先调用元素截图能力，将图保存在服务端，再识别。元素在 iframe 时，先通过 `list_frames` 确定对应 frame，再传 `frame` 参数。元素截图失败会直接返回失败，不会继续 OCR。

## 3. 判断识别是否成功

OCR 结果放在 `data` 内。必须同时检查外层 `ok` 和内层 `data.ok`：外层成功可能只表示命令正常返回，内层仍可能是识别失败。

以下是省略部分字段的示意响应，内容为虚构文本：

```json
{
  "ok":true,
  "code":1,
  "data":{
    "ok":true,
    "text":"示例公告：系统维护中",
    "language":"zh-Hans-CN",
    "lineCount":1,
    "ms":120,
    "target":"path=tmp/sample-notice.png",
    "imagePath":"<服务端图片绝对路径>"
  }
}
```

| 字段 | 含义 |
| --- | --- |
| `data.ok` | OCR 是否成功完成；成功不代表文字完全正确 |
| `text` | 识别到的文本，可能为空 |
| `lineCount` | 返回文本的行数 |
| `ms` | 已取得的执行耗时；早期失败不保证存在 |
| `imagePath` | 实际读取图片的服务端路径 |
| `imageUrl` | 有可用图片地址时附带，不保证所有本地文件都可以通过 HTTP 访问 |
| `error`、`hint` | 失败原因及可能的处理建议 |
| `engineMissing` | 没有可用 OCR 引擎时可能返回 `true` |
| `ocrSupported` | 失败时附带的环境检查结果，仅表示能否定位 Windows PowerShell，不证明语言包可用 |

当前返回值没有逐字置信度、文字坐标或实际引擎语言信息。不要按源码注释中的字段设想编写客户端，应以实际返回结构为准。

## 4. 与人工协作结合

`request_human_input` 可以在请求协助时附带识别结果：

```json
{
  "id":"1001",
  "method":"request_human_input",
  "params":{
    "prompt":"请核对图片中的公告内容",
    "selector":"#notice-image",
    "ocr":true,
    "ocrLanguage":"zh-Hans-CN",
    "timeoutSeconds":300
  }
}
```

这里参数名是 `ocrLanguage`，而 `ocr_image` 使用 `language`。结果可能包含 `ocr`、`ocrText` 或 `ocrError`。接口创建请求成功不代表用户已经收到通知，宿主仍需展示求助信息。

OCR 只能提供文字参考，不能证明登录、短信验证、扫码或人工确认已经完成。遇到需要本人操作的验证时，应保留浏览器状态，等待真实答复，再读取页面确认结果。

## 5. 常见问题与数据保护

| 现象 | 排查方式 |
| --- | --- |
| 外层成功但没有文字 | 检查 `data.ok`、`error` 和 `engineMissing`；再看 `data.engine` 确认这次是谁读的 |
| 找不到图片 | 检查服务进程工作目录、文件是否存在、访问权限以及是否误传客户端路径 |
| 环境支持但引擎缺失 | 检查所需 OCR 语言包；环境检测不会验证语言包 |
| 中文内容识别错误 | 检查语言包、原图清晰度、旋转角度、裁剪范围；关键字段人工核对 |
| 整页扫描件/表格截图识别成一堆错乱片段 | 系统 OCR 只擅长短文本。改用外部命令后端（第 6 节），并把 `download_image` 拿到的**原始文件**交给它 |
| 配了 `engine=command` 却好像没生效 | 看 `get_config` 的 `ocr.describe`：命令为空时会如实说明退回了系统 OCR |
| 页面元素找不到 | 重新获取快照，确认选择器、页签和 iframe |
| 上传或截图后读错图 | 核对 `target`、`imagePath`，不要继续使用旧索引 |

本地识别不代表所有结果都不会留档。页面截图、命令响应、trace、临时参数文件可能包含证照与个人信息，分享前按[留档脱敏说明](<https://deepseek-browser-use.io.nexus/09>)核验。教程仅使用虚构图片与占位路径，不复制实际证照、手机号、验证码或账号。

## 6. 外部命令后端（整页文档识别）

系统 OCR 擅长短文本（验证码、维护提示图），遇到**整页扫描件、票据、带合并单元格的表格截图**给出的却是错乱片段。这时把它换成外部文档 OCR 命令：

```properties
browser.ocr.engine=command
browser.ocr.command=java -jar D:/tools/ocr-cli.jar -i "{input}" -o "{output}"
browser.ocr.timeoutMs=120000
```

| 占位符 | 含义 |
| --- | --- |
| `{input}` | 图片路径（服务端本地文件） |
| `{output}` | 结果文本路径；模板里给了它就从文件读结果，没给就读 stdout |
| `{language}` | 识别语言，默认 `zh-Hans-CN` |

- **带空格或中文的路径必须用双引号包住**：Windows 上工具装在 `C:\Program Files\…` 是常态，命令是按空白切分的（只认双引号）。
- 命令以退出码 0 结束但**没有任何输出**时按失败处理，并如实写出退出码。
- 外部命令失败**不会静默退回系统 OCR**：调用方明确要的是文档级识别，悄悄换个识别质量差一截的后端，只会让人以为「这张图读不出来」。
- 失败回执里带 `engineHint`，指明是命令本身没跑通（可以先手工执行同一条命令确认工具可用），还是系统 OCR 的能力边界。

完整链路：

```text
get_browser_state 的 mediaCount 非空（或正文写着"详见附件"）
  → download_image（拿原始文件与服务端 path）
  → ocr_image -p path=…（读文字；表格通常以 HTML 或 Markdown 形式返回）
  → 结果过长就用 find_text 只取关心的几行
```
