Appearance
手写体 OCR 识别接口文档
1. 服务概述
1.1 简介
该服务基于有道智云手写文字识别 API,提供了便捷的手写体识别功能封装。主要特点包括:
- 支持多种输入方式(本地文件、URL、二进制数据)
- 自动图片压缩和优化
- 内置缓存机制
- 完善的错误处理
1.2 功能特性
- 支持中英文手写体识别
- 支持多种图片格式(JPG、PNG、BMP)
- 自动图片压缩(超过1MB自动压缩)
- 异常重试机制
- 结果缓存优化
2. 快速开始
2.1 环境要求
- Python 3.6+
- 依赖包:
- requests
- Pillow
- python-json
2.2 安装配置
- 下载官方提供的 Python 示例并打开.
- 安装依赖
bash
pip install requests Pillow
- 获取有道智云认证信息
- 登录有道智云平台
- 创建应用并获取应用ID(APP_KEY)和密钥(APP_SECRET)
- 创建
ocr_service.py
文件
python
import base64
import json
from io import BytesIO
import requests
import time
from functools import lru_cache
from PIL import Image
from utils.AuthV3Util import addAuthParams
import os
class OCRService:
def __init__(self, app_key, app_secret):
"""初始化OCR服务"""
self.app_key = app_key
self.app_secret = app_secret
self.api_url = 'https://openapi.youdao.com/ocr_hand_writing'
def _compress_image(self, data, max_size=1024*1024):
"""内部方法:压缩图片"""
try:
img = Image.open(BytesIO(data))
if len(data) <= max_size:
return data
ratio = (max_size / len(data)) ** 0.5
new_size = (int(img.width * ratio), int(img.height * ratio))
img = img.resize(new_size, Image.Resampling.LANCZOS)
buffered = BytesIO()
img.save(buffered, format=img.format if img.format else 'JPEG',
quality=85, optimize=True)
return buffered.getvalue()
except Exception as e:
raise Exception(f"图片压缩失败: {str(e)}")
def _read_image(self, source):
"""内部方法:读取图片(支持文件路径、URL和二进制数据)"""
try:
if isinstance(source, bytes):
return source
elif isinstance(source, str):
if source.startswith(('http://', 'https://')):
response = requests.get(source, timeout=10)
return response.content
else:
with open(source, 'rb') as f:
return f.read()
else:
raise ValueError("不支持的图片源类型")
except Exception as e:
raise Exception(f"图片读取失败: {str(e)}")
def _process_image(self, image_source):
"""内部方法:处理图片(读取、压缩、编码)"""
try:
# 读取图片
image_data = self._read_image(image_source)
# 压缩图片
compressed_data = self._compress_image(image_data)
# Base64编码
return str(base64.b64encode(compressed_data), 'utf-8')
except Exception as e:
raise Exception(f"图片处理失败: {str(e)}")
@lru_cache(maxsize=100)
def recognize(self, image_source, lang_type='en'):
"""
识别图片中的手写文字
参数:
image_source: 可以是以下三种类型之一:
- 图片文件路径(字符串)
- 图片URL(字符串)
- 图片二进制数据(bytes)
lang_type: 识别语言类型(默认:en)
支持:zh-CHS(中文)、en(英语)、ja(日语)、ko(韩语)等
返回:
dict: {
'success': bool, # 是否成功
'data': dict, # 成功时返回识别结果
'error': str, # 失败时返回错误信息
'time_cost': float # 处理耗时(秒)
}
"""
start_time = time.time()
try:
# 处理图片
img_base64 = self._process_image(image_source)
# 准备请求参数
data = {
'img': img_base64,
'langType': lang_type,
'angle': '0',
'concatLines': '0',
'imageType': '1',
'docType': 'json'
}
# 添加认证参数
addAuthParams(self.app_key, self.app_secret, data)
# 发送请求
headers = {'Content-Type': 'application/x-www-form-urlencoded'}
response = requests.post(self.api_url, data=data, headers=headers, timeout=30)
result = response.json()
# 处理结果
if result.get('errorCode') == '0':
return {
'success': True,
'data': [p['text'] for p in result['Result']['paragraphs']],
'error': None,
'time_cost': time.time() - start_time
}
else:
return {
'success': False,
'data': None,
'error': f"API错误: {result.get('errorCode')}",
'time_cost': time.time() - start_time
}
except Exception as e:
return {
'success': False,
'data': None,
'error': str(e),
'time_cost': time.time() - start_time
}
def get_ocr_service(app_key=None, app_secret=None):
"""获取OCR服务实例"""
# 如果未提供密钥,则从环境变量获取
app_key = app_key or os.getenv('YOUDAO_APP_KEY')
app_secret = app_secret or os.getenv('YOUDAO_APP_SECRET')
if not app_key or not app_secret:
raise ValueError("请提供有道智云的APP_KEY和APP_SECRET")
return OCRService(app_key, app_secret)
- 初始化服务
python
from ocr_service import get_ocr_service
# 方式1:通过环境变量配置(推荐)
# 需要先设置环境变量:
# export YOUDAO_APP_KEY='your_app_key'
# export YOUDAO_APP_SECRET='your_app_secret'
ocr_service = get_ocr_service()
# 方式2:直接传入配置
ocr_service = get_ocr_service(
app_key='YOUR_APP_KEY',
app_secret='YOUR_APP_SECRET'
)
3. API 文档
3.1 recognize 方法
识别图片中的手写文字。
参数说明
参数 | 类型 | 必填 | 说明 |
---|---|---|---|
image_source | str/bytes | 是 | 图片来源,支持本地路径、URL或二进制数据 |
lang_type | str | 否 | 识别语言,默认'en',可选:'zh-CHS'(中文)、'en'(英文) |
返回值
python
{
'success': bool, # 是否成功
'data': list, # 识别结果文本列表(段落为元素)
'error': str, # 错误信息(如果失败)
'time_cost': float # 处理耗时(秒)
}
使用示例
- 识别本地图片
python
# 本地文件识别
result = ocr_service.recognize('path/to/image.jpg', lang_type='zh-CHS')
- 识别网络图片
python
# 网络图片识别
url = 'https://example.com/image.jpg'
result = ocr_service.recognize(url, lang_type='en')
- 处理识别结果
python
if result['success']:
result = ocr_service.recognize(test_image, lang_type='zh-CHS')
print(json.dumps(result, indent=4, ensure_ascii=False))
else:
print(f"识别失败: {result['error']}")
- 案例
对于图片
识别结果为
{
"success": true,
"data": [
"第二节(25分)",
"Paragraph 1: When Mom returned to the car, everything was just as she had left it. When my mother arrived home. I planed to help her take the things back home as usual but things in order surprised me. I asked my mother how she do that. \"Well, just as the old saying goes. Curiosity killed the cat, but satisfaction brought him back. I just let Tammy know what was in my bag.\"After that time, Tommy could go shopping with my mother again.",
"-",
"-",
"-",
"-",
"-",
"-",
"Paragraph 2: I was wrong when I thought Tammy was the only dog to have such a strange curiosity. Several weeks ago, our neighbor gave us a lovely little dog and we named him Holly. One day, my mother went shopping as usual with Tammy and little Holly. She showed each item to Tammy and put it back, then she left the dogs. Tammy didn't look at the bag but Holly was looking at it with curiosity. So when my mother returned to the car and opened the door, she shouted. \"My bags!\" - -"
],
"error": null,
"time_cost": 0.7689785957336426
}
data
为识别结果文本列表,每个元素为一段落。
4. 错误码说明
4.1 服务错误码
错误码 | 说明 | 处理建议 |
---|---|---|
0 | 成功 | - |
102 | 不支持的语言类型 | 检查 lang_type 参数 |
108 | 应用ID无效 | 检查 APP_KEY |
110 | 无效签名 | 检查 APP_SECRET |
401 | 账户已欠费 | 检查账户余额 |
411 | 访问频率受限 | 控制调用频率 |
4.2 系统错误码
错误类型 | 说明 | 处理建议 |
---|---|---|
图片读取失败 | 无法读取或下载图片 | 检查图片路径或URL |
图片格式错误 | 不支持的图片格式 | 使用支持的图片格式 |
网络超时 | API调用超时 | 检查网络连接 |
5. 最佳实践
5.1 图片要求
- 支持格式:JPG、PNG、BMP
- 建议大小:不超过1MB
- 图片质量:清晰、对比度适中
- 背景:简单、纯色背景效果更好
5.2 性能优化
- 使用URL方式替代本地文件可减少IO
- 对重复识别的图片利用缓存机制
- 批量处理时注意调用频率限制
5.3 错误处理
python
try:
result = ocr_service.recognize(image_path)
if not result['success']:
# 处理业务错误
logger.error(f"识别失败: {result['error']}")
except Exception as e:
# 处理系统错误
logger.error(f"系统错误: {str(e)}")
6. 注意事项
安全性
- 请勿在客户端暴露 APP_SECRET
- 建议使用环境变量管理密钥
- 使用HTTPS传输图片
限制说明
- 单张图片大小限制:4MB
- QPS限制:根据账户类型不同有所区别
- 总调用量限制:见有道智云控制台
成本优化
- 合理使用缓存机制
- 图片预处理减少无效调用
- 控制图片大小降低成本