qwen / image-ocr
基于通义千问大模型的图片文字识别与JSON结构化输出库
Requires
- php: >=7.2
- guzzlehttp/guzzle: ^6.5|^7.0
Requires (Dev)
- phpunit/phpunit: ^8.0
This package is not auto-updated.
Last update: 2026-05-08 08:19:28 UTC
README
基于通义千问视觉大模型(qwen-vl-ocr)的图片文字识别与 JSON 结构化输出 PHP 库。
通过调用阿里云 DashScope API,将图片中的文字内容智能识别并自动解析为结构化 JSON 数据。内置 9 种中国常见证件/票据类型的专用识别模板,开箱即用。
特性
- 基于 PHP 7.2+,使用 Guzzle HTTP 客户端
- 调用通义千问视觉模型(qwen-vl-ocr)识别图片中的文字
- 自动解析模型返回的 JSON 结构化数据(支持纯 JSON 和 Markdown 代码块格式)
- 内置 9 种证件/票据类型专用 Prompt 模板,精准提取字段
- 支持自定义 Prompt 指令和 PromptBuilder 替换
- 完善的异常处理(区分 API 请求异常和 JSON 解析异常)
- 支持 URL 和 Base64 两种图片输入方式
支持的证件类型
| 类型 | 类名 | 标识符 | 说明 |
|---|---|---|---|
| 身份证正面 | FrontIdCard |
frontIdCard |
姓名、性别、民族、出生日期、住址、身份证号 |
| 身份证背面 | BackIdCard |
backIdCard |
签发机关、有效期限 |
| 营业执照 | BusinessLicense |
businessLicense |
统一社会信用代码、企业名称、法人、经营范围等 14 个字段 |
| 车辆合格证 | Certificate |
certificate |
合格证编号、车架号、发动机号等 38 个字段 |
| 发票 | CarInvoice |
carInvoice |
发票代码、金额、购销双方信息、明细行等 27 个字段 |
| 行驶证正页 | FrontLicense |
frontLicense |
号牌号码、车辆类型、所有人、VIN 等 11 个字段 |
| 行驶证副页 | BackLicense |
backLicense |
核定载人数、总质量、外廓尺寸等 12 个字段 |
| 驾驶证正面 | FrontDrivingLicense |
frontDrivingLicense |
证号、姓名、准驾类型、有效期限等 11 个字段 |
| 驾驶证背面 | BackDrivingLicense |
backDrivingLicense |
姓名、档案编号、记录、证号 |
安装
composer require qwen/image-ocr
阿里云 Qwen 模型计费价格
| 模型 | 类型 | 输入价格 | 输出价格 |
|---|---|---|---|
| qwen-vl-ocr | 视觉识别 · OCR 专项 | ¥0.3 / 百万 token | ¥0.5 / 百万 token |
| qwen-vl-plus-latest | 视觉理解 · 多模态增强 | ¥0.8 / 百万 token | ¥2.0 / 百万 token |
计费单位:元(CNY)/ 每百万 token
仅需 OCR 文字识别,降低成本,默认使用 qwen-vl-ocr 模型;存在手写识别可切换为 qwen-vl-plus-latest
$client = new Client('sk-xxxxxxxx', [ 'model' => 'qwen-vl-plus-latest', ]);
快速开始
1. 通用文字识别
使用默认 Prompt,识别图片中所有文字并输出结构化 JSON:
<?php require 'vendor/autoload.php'; use Qwen\ImageOcr\Client; $client = new Client('sk-xxxxxxxx'); $result = $client->recognize('https://example.com/image.jpg'); print_r($result->getData()); echo $result->toJson();
2. 自定义 Prompt 识别
传入自定义指令,控制模型的输出格式:
$instruction = '请识别图片中的所有文字,并按表格形式输出为 JSON'; $result = $client->recognizeWithPrompt('https://example.com/table.jpg', $instruction); echo $result->toJson();
3. 按证件类型识别(推荐)
使用内置的证件类型模板,精准提取特定字段:
use Qwen\ImageOcr\OcrType\FrontIdCard; use Qwen\ImageOcr\OcrType\BusinessLicense; // 身份证正面 $result = $client->recognizeAs('https://example.com/id-front.jpg', new FrontIdCard()); echo $result->get('idNumber'); // 18位身份证号码 // 营业执照 $result = $client->recognizeAs('https://example.com/license.jpg', new BusinessLicense()); echo $result->get('companyName'); // 企业名称
4. 使用 Base64 图片
支持 base64 data URI 格式的图片输入:
$base64Image = 'data:image/jpeg;base64,/9j/4AAQSkZJRg...'; $result = $client->recognize($base64Image);
证件类型识别示例
以下示例展示了所有 9 种证件类型的调用方式:
<?php require 'vendor/autoload.php'; use Qwen\ImageOcr\Client; use Qwen\ImageOcr\OcrType\BusinessLicense; use Qwen\ImageOcr\OcrType\Certificate; use Qwen\ImageOcr\OcrType\FrontIdCard; use Qwen\ImageOcr\OcrType\BackIdCard; use Qwen\ImageOcr\OcrType\CarInvoice; use Qwen\ImageOcr\OcrType\FrontLicense; use Qwen\ImageOcr\OcrType\BackLicense; use Qwen\ImageOcr\OcrType\FrontDrivingLicense; use Qwen\ImageOcr\OcrType\BackDrivingLicense; use Qwen\ImageOcr\Exception\ApiException; use Qwen\ImageOcr\Exception\OcrException; $client = new Client('sk-xxxxxxxx'); // 营业执照 $result = $client->recognizeAs('https://example.com/business-license.jpg', new BusinessLicense()); // 输出字段:creditCode, companyName, companyType, businessAddress, legalPerson, // businessScope, registeredCapital, RegistrationDate, validPeriod, // validFromDate, validToDate, companyForm, issueDate, title // 车辆合格证 $result = $client->recognizeAs('https://example.com/certificate.jpg', new Certificate()); // 输出字段:certificateNumber, vinCode, vehicleModel, vehicleName, vehicleBrand, // manufactureName, engineModel, engineNumber, fuelType, displacement 等 38 个字段 // 身份证正面 $result = $client->recognizeAs('https://example.com/id-front.jpg', new FrontIdCard()); // 输出字段:name, sex, ethnicity, birthDate, address, idNumber // 身份证背面 $result = $client->recognizeAs('https://example.com/id-back.jpg', new BackIdCard()); // 输出字段:issueAuthority, validPeriod // 发票 $result = $client->recognizeAs('https://example.com/invoice.jpg', new CarInvoice()); // 输出字段:invoiceCode, invoiceNumber, invoiceDate, purchaserName, sellerName, // totalAmount, invoiceDetails[] 等 27 个字段 // 行驶证正页 $result = $client->recognizeAs('https://example.com/vehicle-front.jpg', new FrontLicense()); // 输出字段:licensePlateNumber, vehicleType, owner, model, vinCode, engineNumber 等 // 行驶证副页 $result = $client->recognizeAs('https://example.com/vehicle-back.jpg', new BackLicense()); // 输出字段:licensePlateNumber, passengerCapacity, totalWeight, curbWeight 等 // 驾驶证正面 $result = $client->recognizeAs('https://example.com/driving-front.jpg', new FrontDrivingLicense()); // 输出字段:licenseNumber, name, sex, approvedType, validFromDate, validPeriod 等 // 驾驶证背面 $result = $client->recognizeAs('https://example.com/driving-back.jpg', new BackDrivingLicense()); // 输出字段:name, recordNumber, record, licenseNumber
API 文档
Client
客户端核心类,提供三种识别方法。
__construct($apiKeyOrConfig, array $options = [])
创建客户端实例。
参数:
$apiKeyOrConfig:API Key 字符串或Config实例$options:可选配置数组base_url:API 端点(默认:https://dashscope.aliyuncs.com/compatible-mode/v1)model:模型名称(默认:qwen-vl-ocr)timeout:请求超时秒数(默认:60)temperature:采样温度 [0, 2](默认:0,确定性输出)top_p:核采样阈值 (0, 1],与 temperature 二选一top_k:候选 Token 数量(默认:20)enable_thinking:是否开启混合思考模式(默认:false)
// 使用 API Key 字符串 $client = new Client('sk-xxxxxxxx'); // 自定义配置 $client = new Client('sk-xxxxxxxx', [ 'timeout' => 120, 'model' => 'qwen-vl-max', ]); // 使用 Config 对象 $config = new Config('sk-xxxxxxxx', [ 'base_url' => 'https://custom-endpoint.com/v1', 'model' => 'qwen-vl-max', 'timeout' => 90, ]); $client = new Client($config);
recognize(string $imageUrl): OcrResult
通用文字识别,使用默认 Prompt 提取图片中所有文字并结构化输出。
参数: $imageUrl — 图片 URL 或 base64 data URI
recognizeWithPrompt(string $imageUrl, string $instruction): OcrResult
使用自定义 Prompt 识别图片。
参数:
$imageUrl— 图片 URL 或 base64 data URI$instruction— 自定义指令文本
recognizeAs(string $imageUrl, OcrTypeInterface $type): OcrResult
按业务类型识别图片,使用证件类型专属的 system/user Prompt。
参数:
$imageUrl— 图片 URL 或 base64 data URI$type— 证件类型对象(实现OcrTypeInterface接口)
setPromptBuilder(PromptBuilder $builder): self
替换默认 PromptBuilder,用于高级定制。
setHttpClient(HttpClient $client): self
替换默认 Guzzle HttpClient,用于测试或代理场景。
OcrResult
识别结果封装类。
| 方法 | 返回类型 | 说明 |
|---|---|---|
getData() |
array |
获取解析后的结构化数组 |
getRawText() |
string |
获取模型返回的原始文本(可能包含 Markdown 代码块) |
getRawResponse() |
array |
获取完整的 API 响应数组 |
toJson(int $flags) |
string |
将结构化数据序列化为 JSON 字符串 |
get(string $key, $default) |
mixed |
快捷访问结构化数据中的某个键 |
$result = $client->recognizeAs($url, new FrontIdCard()); $result->get('idNumber'); // "110101199001011234" $result->get('name'); // "张三" $result->get('notExist', '默认值'); // "默认值" $result->getData(); // 完整数组 $result->toJson(); // JSON 字符串 $result->getRawText(); // 模型原始输出 $result->getRawResponse(); // API 完整响应
OcrTypeInterface
证件类型接口,所有证件类型对象必须实现。
| 方法 | 说明 |
|---|---|
getSystemPrompt() |
返回系统提示词(role: system 消息内容) |
getUserPrompt() |
返回用户提示词(包含字段提取指令和 JSON 格式要求) |
getTypeName() |
返回证件类型标识符(camelCase) |
自定义证件类型
实现 OcrTypeInterface 接口或继承 AbstractOcrType 抽象类,即可创建自定义证件类型:
use Qwen\ImageOcr\OcrType\AbstractOcrType; class BankCard extends AbstractOcrType { public function getTypeName(): string { return 'bankCard'; } public function getUserPrompt(): string { return <<<'PROMPT' 请识别银行卡图片中的信息,以 JSON 格式输出以下字段: { "bankName": "银行名称", "cardNumber": "银行卡号", "cardType": "卡类型(借记卡/信用卡)", "holderName": "持卡人姓名" } 只输出 JSON,不要包含任何额外说明。如某字段无法识别,对应值设为空字符串。 PROMPT; } } // 使用自定义类型 $result = $client->recognizeAs('https://example.com/bank-card.jpg', new BankCard()); echo $result->get('cardNumber');
异常处理
use Qwen\ImageOcr\Exception\ApiException; use Qwen\ImageOcr\Exception\OcrException; try { $result = $client->recognizeAs($imageUrl, new FrontIdCard()); } catch (ApiException $e) { // API 请求失败(网络错误、认证失败、模型返回错误等) echo "API 错误:" . $e->getMessage(); echo "状态码:" . $e->getStatusCode(); echo "响应体:" . $e->getResponseBody(); } catch (OcrException $e) { // JSON 解析失败或其他业务错误 echo "OCR 错误:" . $e->getMessage(); }
高级用法
自定义 PromptBuilder
use Qwen\ImageOcr\Prompt\PromptBuilder; $builder = new PromptBuilder('请识别图片中的发票信息,输出为 JSON'); $client->setPromptBuilder($builder); $result = $client->recognize($imageUrl);
使用 Config 对象
use Qwen\ImageOcr\Config; use Qwen\ImageOcr\Client; $config = new Config('sk-xxxxxxxx', [ 'base_url' => 'https://dashscope.aliyuncs.com/compatible-mode/v1', 'model' => 'qwen-vl-ocr', 'timeout' => 90, 'temperature' => 0, 'top_k' => 20, 'enable_thinking' => false, ]); $client = new Client($config);
Docker 运行
项目提供了 docker-compose.yml,可快速搭建运行环境:
# 启动容器 docker-compose up -d # 在容器中运行示例脚本 docker exec ocr php /data/examples/probe_types.php # 运行单元测试 docker exec ocr vendor/bin/phpunit # 运行集成测试(需设置环境变量) docker exec -e RUN_INTEGRATION_TESTS=1 -e QWEN_API_KEY=sk-xxxxxxxx ocr vendor/bin/phpunit --testsuite Integration
项目结构
aliocr/
├── src/
│ ├── Client.php # 核心客户端,提供三种识别方法
│ ├── Config.php # 配置管理(API Key、模型、超时等)
│ ├── OcrResult.php # 识别结果封装
│ ├── Exception/
│ │ ├── OcrException.php # 基础异常类
│ │ └── ApiException.php # API 请求异常(含状态码和响应体)
│ ├── OcrType/
│ │ ├── OcrTypeInterface.php # 证件类型接口
│ │ ├── AbstractOcrType.php # 抽象基类(提供默认 system prompt)
│ │ ├── FrontIdCard.php # 身份证正面
│ │ ├── BackIdCard.php # 身份证背面
│ │ ├── BusinessLicense.php # 营业执照
│ │ ├── Certificate.php # 车辆合格证
│ │ ├── CarInvoice.php # 发票
│ │ ├── FrontLicense.php # 行驶证正页
│ │ ├── BackLicense.php # 行驶证副页
│ │ ├── FrontDrivingLicense.php # 驾驶证正面
│ │ └── BackDrivingLicense.php # 驾驶证背面
│ ├── Parser/
│ │ └── JsonParser.php # JSON 解析器(支持 Markdown 代码块提取)
│ └── Prompt/
│ └── PromptBuilder.php # Prompt 构建器
├── examples/
│ └── probe_types.php # 证件类型探测示例脚本
├── tests/
│ ├── Integration/
│ │ └── RecognizeTest.php # 集成测试(真实 API 调用)
│ └── Unit/
│ ├── ClientTest.php
│ ├── ConfigTest.php
│ ├── JsonParserTest.php
│ ├── OcrResultTest.php
│ └── PromptBuilderTest.php
├── composer.json
├── docker-compose.yml
├── phpunit.xml
└── README.md
系统要求
- PHP >= 7.2
- Guzzle HTTP 客户端 ^6.5 或 ^7.0
- 阿里云 DashScope API Key
许可证
MIT License