公式识别 API 文档

接口说明

公式识别是将图片(来源如扫描仪或数码相机)中的数学公式及题干,转换化为可编辑的标准LaTeX公式及文本。覆盖小学、初中、高中等多种题型,详细请参照 公式题型 。目前仅支持拍照印刷体,拍照手写体、扫描印刷体、扫描手写体等后期逐步开放,敬请期待。

该能力是通过HTTP API的方式给开发者提供一个通用的接口。HTTP API适用于一次性交互数据传输的AI服务场景,比如上传图片识别其中的文字等;相较于SDK,API具有轻量、跨语言的特点。另外,请注意该接口使用的HTTP API协议不支持跨域。

接口Demo

示例demo请点击 这里 下载。
目前仅提供部分开发语言的demo,其他语言请参照下方接口文档进行开发。
也欢迎热心的开发者到 讯飞开放平台社区 分享你们的demo。

接口要求

集成公式识别API时,需按照以下要求。

内容 说明
传输方式 http[s] (为提高安全性,强烈推荐https)
请求地址 http[s]: //rest-api.xfyun.cn/v2/itr
注:服务器IP不固定,为保证您的接口稳定,请勿通过指定IP的方式调用接口,使用域名方式调用
请求行 POST /v2/itr HTTP/1.1
接口鉴权 签名机制,详情请参照下方鉴权认证
字符编码 UTF-8
响应格式 统一采用JSON格式
开发语言 任意,只要可以向讯飞云服务发起HTTP请求的均可
适用范围 任意操作系统,但因不支持跨域不适用于浏览器
图片属性 最短边至少15px,最长边最大4096px,支持文字与水平轴小于±15°夹角偏转
图片格式 jpg/png/bmp
图片大小 base64编码后大小不超过4M

接口调用流程

· 通过接口密钥基于hmac-sha256计算签名,将签名以及其他参数放在Http Request Header中。详见下方 鉴权认证
· 将请求参数以及图片数据放在Http Request Body中,以POST表单的形式提交,详见下方 请求参数
· 向服务器端发送Http请求后,接收服务器端的返回结果。

白名单

默认关闭IP白名单,即该服务不限制调用IP。
在调用该业务接口时

  • 若关闭IP白名单,接口认为IP不限,不会校验IP;
  • 若打开IP白名单,则服务端会检查调用方IP是否在讯飞开放平台配置的IP白名单中,对于没有配置到白名单中的IP发来的请求,服务端会拒绝服务。

IP白名单规则

  • 在 控制台-相应服务的IP白名单处编辑,保存后五分钟左右生效;
  • 不同Appid的不同服务都需要分别设置IP白名单;
  • IP白名单需设置为外网IP,请勿设置局域网IP;
  • 如果握手阶段返回{"message":"Your IP address is not allowed"},则表示由于IP白名单配置有误或还未生效,服务端拒绝服务。

鉴权认证

在调用业务接口时,须对HTTP请求进行签名,服务端通过签名来识别用户并验证其合法性。

鉴权方法

在Http Request Header中配置以下鉴权参数用于授权认证,其中签名信息放在请求头Authorization中。
Header示例:

    Content-Type:application/json
    Accept:application/json,version=1.0
    Host:rest-api.xfyun.cn
    Date:Mon, 18 Mar 2019 08:32:07 GMT
    Digest:SHA-256=MGNjNThlMTU3ZWNmYjU4YTlhNTAwNDI5NWE4NTBmNWM5ZTMwMmM5OGZiNzE2ODY4ZjM2ZTQxYmNjMzkzZjIwYQ==
    Authorization:api_key="your_key", algorithm="hmac-sha256", headers="host date request-line digest", signature="$signature"

鉴权参数:

参数 类型 必须 说明 示例
Host string 请求主机 rest-api.xfyun.cn
Date string 当前时间戳,RFC1123格式("EEE, dd MMM yyyy HH:mm:ss z") Tue, 30 Jul 2019 07:51:27 GMT
Digest string 加密请求body
SHA-256=Base64(SHA256(请求body))
body请参考下方公共请求参数
SHA-256=AmSJeAtB....
Authorization string 使用base64编码的签名相关信息(签名基于hamc-sha256计算) 参考下方签名详细生成规则

· date参数生成规则:

date必须是UTC+0或GMT时区,RFC1123格式(Tue, 30 Jul 2019 07:51:27 GMT)。
服务端会对Date进行时钟偏移检查,最大允许300秒的偏差,超出偏差的请求都将被拒绝。

· Authorization参数生成格式:

    Authorization: api_key="your_key", algorithm="hmac-sha256", headers="host date request-line digest", signature="$signature"
    示例:api_key="apikeyXXXXXXXXXXXXXXXXXXXXXXXXXX", algorithm="hmac-sha256", headers="host date request-line digest", signature="RhJ/0FO+Df2zuTQcseN1jxRoonKeuKi0wXRByQUgIA0="

其中 api_key 是在控制台获取的APIKey(在控制台的公式识别页面可查看,为32位字符串。),这里以api_key="apikeyXXXXXXXXXXXXXXXXXXXXXXXXXX"为例
algorithm 是加密算法(仅支持hmac-sha256),headers 是参与签名的参数。
signature 是使用加密算法对参与签名的参数签名后并使用base64编码的字符串,详见下方。

· signature参数生成规则:

signature原始字段由 host,date,request-line,digest四个参数按照格式拼接成,
拼接的格式为(\n为换行符,’:’后面有一个空格): host: $host\ndate: $date\n$request-line\ndigest: $digest

例如,请求的url为:https://rest-api.xfyun.cn/v2/itr
请求的body为:{"common":{"app_id":"5dXXXXXX"},"business":{"ent":"teach-photo-print","aue":"raw"},"data":{"image":"/9j/4AAQSkZJRgABAQAAAQABAA...."}}
则signature生成步骤如下:

1)对请求body进行SHA256计算,把计算结果进行Base64编码后的字符串写在"SHA-256="后,即字段digest的值

    digest: SHA-256=Base64(SHA256(请求body))
    例:digest: SHA-256=AmSJeAtBmL+v9F4RZfeKkubQP2YIuVDkH76yFwyO/Sg=

2)构建signature原始字段(signature_origin)

    host: rest-api.xfyun.cn
    date: Tue, 30 Jul 2019 07:51:27 GMT
    POST /v2/itr HTTP/1.1
    digest: SHA-256=AmSJeAtBmL+v9F4RZfeKkubQP2YIuVDkH76yFwyO/Sg=

3)使用hmac-sha256算法结合apiSecret对signature_origin签名,获得签名后的摘要signature_sha
apiSecret在控制台的公式识别页面可查看,这里以apisecretXXXXXXXXXXXXXXXXXXXXXXX为例

    signature_sha=hmac-sha256(signature_origin,$apiSecret)

4)使用base64编码对signature_sha进行编码,获得最终的signature

    signature=base64(signature_sha)
    例:RhJ/0FO+Df2zuTQcseN1jxRoonKeuKi0wXRByQUgIA0=

鉴权示例(golang)

    package main
    import (
    	"crypto/hmac"
    	"crypto/sha256"
    	"encoding/base64"
    	"fmt"
    	"time"
    	"github.com/valyala/fasthttp"
    )
    const (
    	//支持的算法
    	Algorithm = "hmac-sha256"
    	//版本协议
    	HttpProto = "HTTP/1.1"
    	//假定的secret
    	Secret = "12345"
    )
    func assemblyRequestHeader(req *fasthttp.Request, apiKey, host, uri string, body []byte) {
    	req.Header.Set("Content-Type", "application/json")
    	//设置请求头 其中Host Date 必须有
    	req.Header.Set("Host", host)
    	//date必须是utc时区,且不能和服务器时间相差300s
    	currentTime := time.Now().UTC().Format(time.RFC1123)
    	req.Header.Set("Date", currentTime)
    	//对body进行sha256签名,生成digest头部,POST请求必须对body验证
    	digest := "SHA-256=" + signBody(body)
    	req.Header.Set("Digest", digest)
    	//根据请求头部内容,生成签名
    	sign := generateSignature(host, currentTime,"POST", uri, HttpProto, digest,Secret)
    	//组装Authorization头部
    	authHeader := fmt.Sprintf(`api_key="%s", algorithm="%s", headers="host date request-line digest", signature="%s"`, apiKey, Algorithm, sign)
    	req.Header.Set("Authorization", authHeader)
    }
    func generateSignature(host, date, httpMethod, requestUri, httpProto, digest string, secret string) string {
    	//不是request-line的话,则以 header名称,后跟ASCII冒号:和ASCII空格,再附加header值
    	var signatureStr string
    	if len(host) != 0 {
    		signatureStr = "host: " + host + "\n"
    	}
    	signatureStr += "date: " + date + "\n"
    	//如果是request-line的话,则以 http_method request_uri http_proto
    	signatureStr += httpMethod + " " + requestUri + " " + httpProto + "\n"
    	signatureStr += "digest: " + digest
    	return hmacsign(signatureStr, secret)
    }
    func hmacsign(data, secret string) string {
    	mac := hmac.New(sha256.New, []byte(secret))
    	mac.Write([]byte(data))
    	encodeData := mac.Sum(nil)
    	return base64.StdEncoding.EncodeToString(encodeData)
    }
    func signBody(data []byte) string {
    	//进行sha256签名
    	sha := sha256.New()
    	sha.Write(data)
    	encodeData := sha.Sum(nil)
    	//经过base64转换
    	return base64.StdEncoding.EncodeToString(encodeData)
    }

鉴权结果

如果鉴权失败,则根据不同错误类型返回不同HTTP Code状态码,同时携带错误描述信息,详细错误说明如下:

HTTP Code 说明 错误描述信息 解决方法
401 缺少authorization参数 {“message”:”Unauthorized”} 检查是否有authorization参数,详情见authorization参数详细生成规则
401 签名参数解析失败 {“message”:”HMAC signature cannot be verified”} 检查签名的各个参数是否有缺失是否正确,特别确认下复制的api_key是否正确
401 签名校验失败 {“message”:”HMAC signature does not match”} 签名验证失败,可能原因有很多。
1. 检查api_key,api_secret 是否正确。
2.检查计算签名的参数host,date,request-line是否按照协议要求拼接。
3. 检查signature签名的base64长度是否正常(正常44个字节)。
403 时钟偏移校验失败 {“message”:”HMAC signature cannot be verified, a valid date or x-date header is required for HMAC Authentication”} 检查服务器时间是否标准,相差5分钟以上会报此错误
403 IP白名单校验失败 {"message":"Your IP address is not allowed"} 可在控制台关闭IP白名单,或者检查IP白名单设置的IP地址是否为本机外网IP地址

认证失败返回示例:

    HTTP/1.1 401 Forbidden
    Date: Thu, 06 Dec 2018 07:55:16 GMT
    Content-Length: 116
    Content-Type: text/plain; charset=utf-8
    {
        "message": "HMAC signature does not match"
    }

请求参数

在调用业务接口时,都需要在 Http Request Body 中配置以下参数,请求数据均为json字符串。

参数名 类型 必传 描述
common object 用于上传公共参数
common.app_id string 在平台申请的appid信息
business object 用于上传业务参数
business.ent string 请求引擎类型,只支持teach-photo-print
business.aue string 预留压缩格式,暂时只支持raw
data object 用于上传识别图像数据
data.image bytes 图像数据,base64编码,要求base64编码后大小不超过4M,最短边至少15px,最长边最大4096px,支持jpg/png/bmp格式

注: base64编码后大小会增加约1/3
请求参数示例:
    {	   
	   "common":{
           "app_id":"xxxxxxxx"
       },
	   "business":{
           "ent":"teach-photo-print",
		   "aue" :"raw"
       },
	   "data":{
		"image":"/9j/4AAQSkZJRgABAQAAAQABAAD/2..."    
	   }
    }

返回参数

参数名 类型 描述
sid string 本次会话id
code int 返回码,0表示成功,其它表示异常,详情请参考错误码
message string 描述信息
data object 公式识别识别返回信息

data字段具体信息
参数名 类型 描述
_engine_info dict 识别引擎相关信息,无需关注
_engine_info.version string 识别引擎版本号
_engine_info.category string 识别引擎参数
_engine_info.name string 识别引擎名称
protocol string 协议版本号
region array 版面分析结果数组,数组中的每个元素为一个识别区域(文本行、图像),元素排序顺序为从上到下,从左至右
region.list[index].type string 识别区域类型,取值为text(文本行)/graph(图像)

若region.list[index].type=text,即文本行,则region元素中除type外,还包含如下信息:

参数名 类型 描述
region.list[index].coord dict 识别区域位置信息
region.list[index].coord.x array 识别区域像素点x坐标列表,其中最小值为识别区域矩形左上角点x坐标,最大值与最小值的差值为矩形宽度。
以上传图片的左上角为原点,横向为x轴(向右为正),纵向为y轴(向下为正)
region.list[index].coord.y array 识别区域像素点y坐标列表,其中最小值为识别区域矩形左上角点y坐标,最大值与最小值的差值为矩形高度。
以上传图片的左上角为原点,横向为x轴(向右为正),纵向为y轴(向下为正)
region.list[index].recog dict 识别区域识别信息
region.list[index].recog.content string 文本行识别结果
其中ifly-latex-begin和ifly-latex-end字段包裹内容是渲染的latex公式
若文本行内部含有图像,以graph:id标记,其中id为graph数组中的序列号
region.list[index].recog.element array 文本行识别结果单字数组(包含文本行中的图像)
region.list[index].recog.element.list[index].content string 文本行单词识别结果
region.list[index].recog.element.list[index].conf float 识别置信度
region.list[index].recog.exception int 异常信息,0代表正常

若region.list[index].type=graph,即图像,则region元素中除type外,还包含如下信息:

参数名 类型 描述
region.list[index].coord dict 识别区域形状和位置信息
region.list[index].coord.x int 识别区域矩形左上角点x坐标
以上传图片的左上角为原点,横向为x轴(向右为正),纵向为y轴(向下为正)
region.list[index].coord.y int 识别区域矩形左上角点y坐标
以上传图片的左上角为原点,横向为x轴(向右为正),纵向为y轴(向下为正)
region.list[index].coord.width int 识别区域矩形宽度
region.list[index].coord.height int 识别区域矩形高度

返回参数示例:

{
  "code": 0,
  "data": {
    "_engine_info": {
      "category": "teaching_assistance_photo",
      "name": "iFlytek-Confucius Engine",
      "version": "2.0.0.1101"
    },
    "protocol": "2.0",
    "region": [
      {
        "coord": {
          "x": [
            "292",
            "290",
            "285",
            "283",
            "280",
            "60",
            "32",
            "23",
            "14",
            "10",
            "8",
            "8",
            "9",
            "11",
            "22",
            "292"
          ],
          "y": [
            "18",
            "48",
            "51",
            "52",
            "52",
            "45",
            "44",
            "43",
            "41",
            "40",
            "38",
            "35",
            "7",
            "5",
            "4",
            "4"
          ]
        },
        "recog": {
          "content": "P(m-4,m+1)",
          "element": [
            {
              "conf": 1,
              "content": "P"
            },
            {
              "conf": 1,
              "content": "("
            },
            {
              "conf": 1,
              "content": "m"
            },
            {
              "conf": 1,
              "content": "-"
            },
            {
              "conf": 1,
              "content": "4"
            },
            {
              "conf": 1,
              "content": ","
            },
            {
              "conf": 1,
              "content": "m"
            },
            {
              "conf": 1,
              "content": "+"
            },
            {
              "conf": 1,
              "content": "1"
            },
            {
              "conf": 1,
              "content": ")"
            }
          ],
          "exception": 0
        },
        "type": "text"
      },
      {
        "coord": {
          "x": [
            "302",
            "298",
            "297",
            "296",
            "291",
            "290",
            "290",
            "293",
            "297",
            "299",
            "302"
          ],
          "y": [
            "48",
            "53",
            "54",
            "54",
            "49",
            "36",
            "24",
            "4",
            "4",
            "6",
            "10"
          ]
        },
        "recog": {
          "content": ".",
          "element": [
            {
              "conf": 1,
              "content": "."
            }
          ],
          "exception": 0
        },
        "type": "text"
      },
      {
        "coord": {
          "x": [
            "243",
            "238",
            "227",
            "217",
            "203",
            "212",
            "243"
          ],
          "y": [
            "54",
            "55",
            "56",
            "56",
            "54",
            "53",
            "53"
          ]
        },
        "recog": {
          "content": "1.",
          "element": [
            {
              "conf": 1,
              "content": "1"
            },
            {
              "conf": 1,
              "content": "."
            }
          ],
          "exception": 0
        },
        "type": "text"
      }
    ]
  },
  "message": "success",
  "sid": "itrXXXXXXXXXXXXXXX"
}

公式题型

No. 题型名称 题型示例
1 平面直角坐标系 示例图片
2 一元二次方程 示例图片
3 概率初步cz 示例图片
4 函数及其图像 示例图片
5 解直角三角形 示例图片
6 平面几何 示例图片
7 投影与视图 示例图片
8 代数 示例图片
9 实数与二次根 示例图片
10 三角形 示例图片
11 相似形 示例图片
12 分式 示例图片
13 统计初步(初中) 示例图片
14 圆锥曲线方程 示例图片
15 直线和圆方程 示例图片
16 直线和平面 示例图片
17 三角函数 示例图片
18 复数 示例图片
19 概率初步gz 示例图片
20 函数和投影 示例图片
21 推理和证明 示例图片
22 平面向量 示例图片

错误码

备注:如出现下述列表中没有的错误码,可到 这里 查询。

错误码 错误描述 说明 处理方式
10029 ITRGetResultJson Error 服务调用失败 检查图片格式是否符合要求
10222 received message larger than max 上传数据超过最大限制 检查上传图片是否超过了4M(base64编码后超过4M)
10313 invalid app_id appid不合法 检查appid是否正确

调用示例

注: demo只是一个简单的调用示例,不适合直接放在复杂多变的生产环境使用

公式识别demo python3语言

公式识别demo java语言

公式识别demo nodejs语言

公式识别demo php语言

注: 其他开发语言请参照 接口调用流程 进行开发,也欢迎热心的开发者到 讯飞开放平台社区 分享你们的demo。

图片样例

公式识别 图片样例 JPG文件

公式识别 图片样例 PNG文件

公式识别 图片样例 BMP文件

注: 如果测试过程中,发现图片符合要求但却不能识别,有可能是由于图片的真实格式和文件后缀不符,请通过图片的二进制流的头文件确认图片真实格式,不符合要求需要进行格式转换。

常见问题

公式识别支持什么应用平台?

答:目前支持Web API应用平台。

公式识别上传什么图片识别效果最佳

答:图片格式仅支持jpeg/png/bmp,图片大小base64编码后≤4M 建议使用清晰的、算式规整、文字与空白占比较大的照片,效果更好。

公式识别交互次数怎么收费

答:公式识别免费500次/天调用,超过可在控制台申请提额。