setting alipay wechat success appmanage dollor user cart order workorder logout left1 left2 app unfree free chart coupon note copy pencil price-tag database cog bin list link plus minus codepen 审核 cross table search user-tie eye github cancel-circle checkmark icon-upload icon-smartphon icon-auth-user icon-arroba-symbol icon-check-pass icon-red-cross icon-pwd-key icon-used icon-expired android appleinc tux windows8 java webAPI mail vip

    # 指尖文字识别 API 文档

    # 接口说明

    指尖文字识别,可检测图片中指尖位置,将指尖处文字转化为计算机可编码的文字。

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

    # 接口Demo

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

    # 接口要求

    集成指尖文字识别API时,需按照以下要求。

    内容 说明
    传输方式 http[s] (为提高安全性,强烈推荐https)
    请求地址 http[s]: //tyocr.xfyun.cn/v2/ocr
    注:服务器IP不固定,为保证您的接口稳定,请勿通过指定IP的方式调用接口,使用域名方式调用
    请求行 POST /v2/ocr HTTP/1.1
    接口鉴权 签名机制,详情请参照下方接口鉴权
    字符编码 UTF-8
    响应格式 统一采用JSON格式
    开发语言 任意,只要可以向讯飞云服务发起HTTP请求的均可
    适用范围 任意操作系统,但因不支持跨域不适用于浏览器
    图片属性 图片分辨率500W像素以上,或者500W像素图片中的部分裁剪区域,图片中文字的高度最好大于24像素,且包含不少于两个指节以上的手部区域
    图片格式 jpg/png/bmp
    图片大小 不超过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:tyocr.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 请求主机 tyocr.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="t/7LrRzy2SqgsGRXnMODNGRdQh24IpejUW9ChsliSa8="
    

    其中 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://tyocr.xfyun.cn/v2/ocr
    请求的body为:{"common":{"app_id":"5dXXXXXX"},"business":{"ent":"fingerocr","mode":"finger+ocr","method":"dynamic","resize_w":1088,"resize_h":1632},"data":{"image":"/9j/4AAQSkZJRgABAQAAAQABAA...."}}
    则signature生成步骤如下:

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

        digest: SHA-256=Base64(SHA256(请求body))
        例:digest: SHA-256=kc4Iim6E4s6rCbkuHMemhXf5pwaI1FJ1XFjlUYuTVgo=
    

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

        host: tyocr.xfyun.cn
        date: Thu, 14 May 2020 09:52:44 GMT
        POST /v2/ocr HTTP/1.1
        digest: SHA-256=kc4Iim6E4s6rCbkuHMemhXf5pwaI1FJ1XFjlUYuTVgo=
    

    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)
        例:t/7LrRzy2SqgsGRXnMODNGRdQh24IpejUW9ChsliSa8=
    

    # 鉴权示例(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 请求引擎类型,只支持fingerocr
    business.mode string 模式,选择范围:finger,finger+ocr(默认值)。
    finger模式:只进行手指检测,返回手指位置、方向、宽度等信息
    finger+ocr模式:进行手指检测以及OCR识别,返回手指指向的字、词、句信息
    business.method string 方法,取值:dynamic(默认值)。根据指尖位置裁剪感兴趣区域(ROI)进行OCR识别
    business.cut_w_scale float 根据指尖位置选取ROI(感兴趣区域)的宽度倍数,即设置ROI的宽度是手指宽度的几倍(宽度= cut_w_scale * 手指宽度),默认3.0,取值范围:[0,65536]
    business.cut_h_scale float 根据指尖位置选取ROI(感兴趣区域)的高度倍数,即设置ROI的高度是手指宽度的几倍(高度= cut_h_scale * 手指宽度),默认1.0,取值范围:[0,65536]
    business.cut_shift float 根据指尖位置选取ROI(感兴趣区域)的往下平移的倍数,即设置ROI往下平移的距离是手指宽度的几倍(平移量= cut_shift * 手指宽度),默认0,取值范围:[0,1]
    business.resize_w int 引擎内部处理模块输入图像宽度,取值范围:[1,65536]。
    若应用端上传图像宽为input_w,scale为缩放系数,则resize_w=input_w*scale。
    若不缩放直接按原图处理,引擎耗时会变长,建议根据实际情况测试以寻求最佳值
    business.resize_h int 引擎内部处理模块输入图像高度,取值范围:[1,65536]。
    若应用端上传图像高为input_h,scale为缩放系数,则resize_h=input_h*scale。
    若不缩放直接按原图处理,引擎耗时会变长,建议根据实际情况测试以寻求最佳值
    data object 用于上传识别图像数据
    data.image bytes 图像数据,base64编码
    大小不超过4M,支持jpg/png/bmp格式
    另外,图片分辨率500W像素以上,或者500W像素图片中的部分裁剪区域,图片中文字高度最好大于24像素,且包含不少于两个指节以上的手部区域,否则会影响识别效果

    请求参数示例:
        {	   
    	   "common":{
               "app_id":"xxxxxxxx"
           },
    	   "business":{
        	   "ent":"fingerocr",
    		   "mode" :"finger+ocr",
    		   "method" :"dynamic",
    		   "resize_w" :1080,
    		   "resize_h" :1080
           },
    	   "data":{
    		"image":"/9j/4AAQSkZJRgABAQAAAQABAAD/2..." 
    	   }
        }
    

    # 返回参数

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

    data字段具体信息
    参数名 类型 描述 备注
    data.finger_ocr object 指尖文字识别结果,仅mode=finger+ocr时返回
    data.finger_ocr.char object “字”结果(列表)
    data.finger_ocr.char.id int 手指所指的字在列表中的id,从0开始计
    data.finger_ocr.char.list[index].content string “字”内容
    data.finger_ocr.char.list[index].coord array “字”所在框的坐标,单位:像素
    data.finger_ocr.char.list[index].score float 得分,可以理解为这个字和指尖位置的距离(根据这个值,可以判断哪个字离手指最近),分值越高代表距离越远
    data.finger_ocr.word object “词”结果(列表)
    data.finger_ocr.word.id int 手指所指的词在列表中的id,从0开始计
    data.finger_ocr.word.list[index].content string “词”内容
    data.finger_ocr.word.list[index].coord array “词”所在框的坐标
    data.finger_ocr.word.list[index].score float 得分,可以理解为这个词和指尖位置的距离(根据这个值,可以判断哪个词离手指最近),分值越高代表距离越远
    data.finger_ocr.sent object “句”结果,较“字”“词”结果列表返回文本会更长,引擎会在指定的ROI范围内向前追溯判断更完整的语句,作为“句”结果返回
    data.finger_ocr.sent.content string “句”内容(仅支持英文整句结果,中文效果待优化)
    data.finger_ocr.sent.coord array “句”所在框的坐标,单位:像素
    data.finger_pos object 手指信息
    data.finger_pos.angle float 手指方向,范围[-180,180]
    data.finger_pos.dir_x float 手指方向向量坐标(x)
    data.finger_pos.dir_y float 手指方向向量坐标(y)
    data.finger_pos.pos_x float 手指位置坐标(x)
    data.finger_pos.pos_y float 手指位置坐标(y)
    data.height int 预留字段,暂无需关注
    data.width int 预留字段,暂无需关注
    data.mode int 识别模式:finger,finger+ocr。
    finger模式:只进行手指检测,返回手指位置、方向、宽度等信息
    finger+ocr模式:进行手指检测以及OCR识别,返回手指指向的字、词、句信息
    data.version_engine string 引擎版本
    data.version_json string json版本

    注:以上所说的坐标,均是以上传图片的左上角为原点,横向为x轴(向右为正),纵向为y轴(向下为正)。

    返回参数示例(mode=finger):

    {
      "code": 0,
      "data": {
        "finger_pos": {
          "angle": -96.33390045166016,
          "dir_x": -4,
          "dir_y": -36,
          "pos_x": 516,
          "pos_y": 708,
          "thickness": 112.6410217285156
        },
        "height": 0,
        "mode": "finger",
        "version_engine": "V1.0.10",
        "version_json": "1.0",
        "width": 0
      },
      "message": "success",
      "sid": "ocrXXXXXXXXXXXXXXXXXXXXXXXXX"
    }
    

    返回参数示例(mode=finger+ocr):

    {
      "code": 0,
      "data": {
        "finger_ocr": {
          "char": {
            "id": 4,
            "list": [
              {
                "content": "b",
                "coord": [
                  {
                    "x": 448,
                    "y": 665
                  },
                  {
                    "x": 471,
                    "y": 666
                  },
                  {
                    "x": 470,
                    "y": 699
                  },
                  {
                    "x": 447,
                    "y": 698
                  }
                ],
                "score": 62.64982223510742
              },
              {
                "content": "i",
                "coord": [
                  {
                    "x": 472,
                    "y": 666
                  },
                  {
                    "x": 479,
                    "y": 666
                  },
                  {
                    "x": 478,
                    "y": 699
                  },
                  {
                    "x": 471,
                    "y": 699
                  }
                ],
                "score": 48.28302001953125
              },
              {
                "content": "r",
                "coord": [
                  {
                    "x": 480,
                    "y": 666
                  },
                  {
                    "x": 492,
                    "y": 666
                  },
                  {
                    "x": 491,
                    "y": 699
                  },
                  {
                    "x": 479,
                    "y": 699
                  }
                ],
                "score": 39.7555046081543
              },
              {
                "content": "t",
                "coord": [
                  {
                    "x": 493,
                    "y": 666
                  },
                  {
                    "x": 500,
                    "y": 666
                  },
                  {
                    "x": 499,
                    "y": 699
                  },
                  {
                    "x": 492,
                    "y": 699
                  }
                ],
                "score": 32.40756225585938
              },
              {
                "content": "h",
                "coord": [
                  {
                    "x": 501,
                    "y": 666
                  },
                  {
                    "x": 521,
                    "y": 667
                  },
                  {
                    "x": 520,
                    "y": 700
                  },
                  {
                    "x": 500,
                    "y": 699
                  }
                ],
                "score": 25.59785079956055
              },
              {
                "content": "d",
                "coord": [
                  {
                    "x": 522,
                    "y": 667
                  },
                  {
                    "x": 541,
                    "y": 667
                  },
                  {
                    "x": 540,
                    "y": 700
                  },
                  {
                    "x": 521,
                    "y": 700
                  }
                ],
                "score": 28.72716522216797
              },
              {
                "content": "a",
                "coord": [
                  {
                    "x": 542,
                    "y": 667
                  },
                  {
                    "x": 562,
                    "y": 668
                  },
                  {
                    "x": 561,
                    "y": 701
                  },
                  {
                    "x": 541,
                    "y": 700
                  }
                ],
                "score": 42.85148620605469
              },
              {
                "content": "y",
                "coord": [
                  {
                    "x": 563,
                    "y": 668
                  },
                  {
                    "x": 578,
                    "y": 668
                  },
                  {
                    "x": 577,
                    "y": 701
                  },
                  {
                    "x": 562,
                    "y": 701
                  }
                ],
                "score": 58.89184951782227
              },
              {
                "content": ".",
                "coord": [
                  {
                    "x": 579,
                    "y": 668
                  },
                  {
                    "x": 587,
                    "y": 668
                  },
                  {
                    "x": 586,
                    "y": 701
                  },
                  {
                    "x": 578,
                    "y": 701
                  }
                ],
                "score": 999999
              }
            ]
          },
          "sent": {
            "content": "December 1st It was Mocky's birthday",
            "coord": [
              {
                "x": 448,
                "y": 666
              },
              {
                "x": 589,
                "y": 669
              },
              {
                "x": 588,
                "y": 701
              },
              {
                "x": 447,
                "y": 697
              }
            ]
          },
          "word": {
            "id": 0,
            "list": [
              {
                "content": "birthday",
                "coord": [
                  {
                    "x": 448,
                    "y": 665
                  },
                  {
                    "x": 578,
                    "y": 668
                  },
                  {
                    "x": 577,
                    "y": 701
                  },
                  {
                    "x": 447,
                    "y": 698
                  }
                ],
                "score": 60.77083587646484
              },
              {
                "content": ".",
                "coord": [
                  {
                    "x": 579,
                    "y": 668
                  },
                  {
                    "x": 587,
                    "y": 668
                  },
                  {
                    "x": 586,
                    "y": 701
                  },
                  {
                    "x": 578,
                    "y": 701
                  }
                ],
                "score": 999999
              }
            ]
          }
        },
        "finger_pos": {
          "angle": -96.33390045166016,
          "dir_x": -4,
          "dir_y": -36,
          "pos_x": 516,
          "pos_y": 708,
          "thickness": 112.6410217285156
        },
        "height": 0,
        "mode": "finger+ocr",
        "version_engine": "V1.0.10",
        "version_json": "1.0",
        "width": 0
      },
      "message": "success",
      "sid": "ocrXXXXXXXXXXXXXXXXXXXXXXXX"
    }
    

    # 错误码

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

    错误码 错误描述 说明 处理方式
    10222 received message larger than max 上传数据超过最大限制 检查上传图片是否超过了4M
    10313 invalid app_id appid不合法 检查appid是否正确
    10909 IFREAD_WRAPPER_ERR_RUNTIME
    非法数据
    接口执行错误 1. 检查参数设置是否正确,图片格式是否符合要求
    2. 手指检测失败,调整手指摆放问题
    3. ocr识别失败,确认所指区域是否有文字以及文字是否清晰

    # 调用示例

    指尖文字识别demo python3语言

    指尖文字识别demo java语言

    指尖文字识别demo nodejs语言

    指尖文字识别demo php语言

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

    # 图片样例

    指尖文字识别 图片样例 JPG文件

    指尖文字识别 图片样例 BMP文件

    指尖文字识别 图片样例 PNG文件

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

    # 常见问题

    # 指尖文字识别支持什么应用平台?

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

    # 是否支持方向有旋转的文字?

    答:支持文字与水平轴小于±15°夹角偏转。

    # 输入图片要求?

    答:图片大小4M以内,图片分辨率500W像素以上,或者500W像素图片中的部分裁剪区域,图片中文字的高度最好大于24像素,且包含不少于两个指节以上的手部区域,这样的图片识别效果会更好。