手書き認識API

ドラフト・コミュニティグループレポート

このバージョン:
https://wicg.github.io/handwriting-recognition/
編集者:
Jiewei QianGoogle
参加:
GitHub WICG/handwriting-recognition新しい課題未解決の課題
コミット:
GitHub spec.bs コミット

概要

手書き認識APIは、既存のオペレーティングシステム機能を利用して、Webアプリケーションが手書きテキストを認識できるようにします。

この文書のステータス

この仕様は、Web Platform Incubator Community Groupによって公開されました。 これはW3C標準ではなく、またW3C標準化トラック上にもありません。 W3Cコミュニティ貢献者ライセンス契約(CLA)の下で、限定的なオプトアウトやその他の条件が適用されることにご注意ください。 W3Cコミュニティおよびビジネスグループについて詳しくはこちらをご覧ください。

1. はじめに

手書き入力は描画です。描画は人間のペン先の動きをデジタルで再現するために必要な情報を記録します。

ここで提案するAPIは、オペレーティングシステムの機能をWebに公開することを目的としています。手書き認識の機能はOSによって異なることがあるため、このAPIはOS固有の機能と容易に統合できる柔軟な設計を目指します。

ユーザーエージェントはWeb APIのデータ構造(本仕様で定義)を、ホストOSで利用可能なものに変換し、Web APIとOSのAPIを接続することが期待されます。

このAPIは、どのプラットフォームでも同じ動作をする認識を定義しようとはしていません。

1.1. 定義

本仕様では以下の概念を定義します。例として手書きの “WEB” を用います:

Handwriting Concepts

手書き認識器は(通常は外部アプリやサービスで実装される)インターフェイスで、以下を行います:

どのようなものを手書き認識器とみなすかはユーザーエージェントの裁量に委ねられます。

データ変換を通じて手書き認識器に適合する形式に変換するため、ユーザーエージェントは本仕様で定義されたものと手書き認識器で使われる同等の概念をマッチさせるべきです。

OSで利用可能な主な手書き認識器は以下です:

手書き認識器は、Webアプリケーションが手書きをよりよく処理するための追加情報(例:手書きから1文字削除するなど)を出力する場合があります。

セグメンテーションは、書記素(ユーザーが知覚する1文字)をそれを構成するストロークやポイントにマッピングします。書記素は複数のUnicodeコードポイントにまたがる場合があります。

xは1つのUTF-16コードポイントで構成されています:\u0078
g̈は2つのUTF-16コードポイントで構成されています:\u0067\u0308
षिも2つのUTF-16コードポイントで構成されています:\u0937\u093f

手書きテキスト "int" を例にします:

Handwriting Segmentation

アプリケーションが文字 "t" を削除したい場合、描画からストローク3と4を削除することができます。

2. APIイディオム

本仕様で言及されているタスクソースは、手書き認識タスクソースです。

アルゴリズムが手書き認識APIタスク Tをキューに投入するとき、ユーザーエージェントは、グローバルタスクをキューに積み手書き認識タスクソース、およびグローバルオブジェクト現在のレルムレコードを利用します。

特に指定のない限り、アルゴリズム手順で生成されたJavaScriptオブジェクトのレルム現在のレルムレコードとします。

3. 機能クエリ

機能クエリインターフェースは、Webアプリケーションが実装依存の機能を問い合わせて利用可否の判断ができるようにします。

const modelConstraint = { languages: ['zh-CN', 'en'] };
const modelDesc = await navigator.queryHandwritingRecognizer(modelConstraint);

// \`modelDesc\` describes the handwriting recognizer meeting the \`modelConstraint\`.
// If the constraints can't be satisfied, \`modelDesc\` will be null.
{
  textAlternatives: true,
  textSegmentation: true,
  hints: {
    alternatives: true,
    textContext: true,
    inputTypes: ['mouse', 'touch', 'stylus']
  }
}
[SecureContext]
partial interface Navigator {
  Promise<HandwritingRecognizerQueryResult?>
      queryHandwritingRecognizer(HandwritingModelConstraint constraint);
};

dictionary HandwritingModelConstraint {
  required sequence<DOMString> languages;
};

dictionary HandwritingRecognizerQueryResult {
  boolean textAlternatives;
  boolean textSegmentation;
  HandwritingHintsQueryResult hints;
};

dictionary HandwritingHintsQueryResult {
  sequence<HandwritingRecognitionType> recognitionType;
  sequence<HandwritingInputType> inputType;
  boolean textContext;
  boolean alternatives;
};

enum HandwritingRecognitionType{
  "text", "per-character"
};

enum HandwritingInputType {
  "mouse", "stylus", "touch"
};

3.1. queryHandwritingRecognizer(constraint)

このメソッドはWebアプリケーションが基盤となる認識器の機能を問い合わせ、利用するかどうか判断する方法を提供します:

同じHandwritingModelConstraint を使って、createHandwritingRecognizer(constraint) を呼び出し、制約を満たすHandwritingRecognizer を作成できます。

queryHandwritingRecognizer(constraint) メソッドが呼び出されたとき、以下を行います:
  1. もし constraintlanguages メンバーがなければ、指定した値で拒否された Promise として新しい TypeError を返す。

  2. p新しい Promise とする。

  3. 次の手順を 並列に 実行する:

    1. 手書き認識器に適した形式に constraint を変換する

    2. 次のいずれかが真である場合:

      • constraintlanguages メンバーが空の リスト である。

      • ユーザーエージェントが、変換された constraint を満たすプラットフォーム依存の 手書き認識器 を見つけるか作成できない。

      手書き認識 API タスクをキューに入れて pnull で解決し、残りの手順を中止する。

    3. それ以外の場合、手書き認識 API タスクをキューに入れて 次を行う:

      1. result を新しい HandwritingRecognizerQueryResult とする

      2. 手書き認識器の機能記述を変換しresult の全てのメンバーを埋める。

      3. p を解決する に際して result を渡す。

  4. p を返す。

実装はHandwritingRecognizerQueryResult およびHandwritingHintsQueryResultへの変換で次のルールに従うべきです:

3.2. HandwritingModelConstraint 属性

これは、基盤となる手書き認識器が(作成される場合)満たすべき制約を説明します。

また、createHandwritingRecognizer(constraint)で 手書き認識器を作成する際にも使用されます。

languages
認識器が認識すべき言語を示す[BCP47]言語タグのリストです。

複数の言語が指定された場合、認識器は全ての言語を認識できる必要があります。

ユーザーエージェントは、与えられた言語タグのすべての可能なスクリプトを考慮するべきです。例えば、「az-Latn」(ラテン文字のみ対応)だけの認識器は、「az」タグ(アゼルバイジャン語)には使うべきではありません。アゼルバイジャン語はキリル文字("az-Cyrl")でも書かれます。

スクリプトの区別が重要な場合は、最も具体的な言語タグを使うことを検討してください。例:アゼルバイジャン語のラテン表記専用アプリでは"az-Latn"を指定。

一部の認識器は単一言語のみ対応です。より良い相互運用性のために言語ごとに認識器を作成することを推奨します。

3.3. HandwritingRecognizerQueryResult 属性

これは手書き認識器実装の固有機能を記述します。

textAlternatives
実装が1つではなく複数の候補転写を返す場合はtrueとなります。
textSegmentation
実装が各転写のセグメンテーション情報を返すならtrueです。
hints
HandwritingHintsQueryResult オブジェクト。startDrawing()で受け付け可能なヒントを記述します。

3.3.1. HandwritingHintsQueryResult 属性

これは、startDrawing() に任意で渡せるヒント群を記述し、精度や性能アップに役立ちます。

慣例的に、ここの属性名はstartDrawing() メソッドで受け付けるものと一致します。

recognitionType
HandwritingRecognitionType 列挙型のリストで、どのようなテキストが描かれる可能性が高いかを表します。

ヒントを指定しても結果の転写内容がそれに対応することは保証されません。

"text"
普通の文章など、本当の単語を書く自由形式のテキスト。例:日常会話の文。
"per-character"
手書きが独立した書記素(ユーザーが知覚する1文字)で連なる形式。例:シリアル番号やライセンスキー。
inputType
HandwritingInputType 列挙型のリストで、どう描かれたかを表します。
"touch"
指で描かれたもの
"stylus"
スタイラスで描かれたもの
"mouse"
マウスカーソルで描かれたもの
textContext
textContextが受け付けられるかの真偽値。textContextは、ユーザーに見せているテキストや、今回の描画より前の認識済みテキスト文字列を含みます。
alternatives
返す転写候補数の最大値を設定可能ならtrueになります。getPredictionで返される候補数の上限となります。

4. 手書き認識器の作成

HandwritingRecognizer は認識を行うために必要なリソースを管理します。

const modelConstraint = { languages: ['en'] };

try {
  const recognizer = await navigator.createHandwritingRecognizer(modelConstraint);
  // Use \`recognizer\` to perform recognitions.
} catch (err) {
  // The provided model constraint can't be satisfied.
}
[SecureContext]
partial interface Navigator {
  Promise<HandwritingRecognizer>
      createHandwritingRecognizer(HandwritingModelConstraint constraint);
};

4.1. createHandwritingRecognizer(constraint) メソッド

このメソッドは、与えられたHandwritingModelConstraint を満たし、認識を行うために必要なリソースを予約するHandwritingRecognizer オブジェクトを生成します。これは手書き認識器へのエントリーポイントです。

ユーザーエージェントは、ユーザーに手書きモデルのインストールやダウンロードを促す場合があります。Webアプリケーションは、このメソッドが常に即座に解決するとは限らないと想定してください。

createHandwritingRecognizer(constraint) メソッドが呼び出されたときは、次のようにします:
  1. constraintlanguages メンバーがなければ、TypeErrorでpromiseをリジェクトします。

  2. p新しいpromiseとします。

  3. 次のステップを並列で実行します:

    1. constraint をプラットフォーム依存の認識器作成に適した形に変換します。

    2. 手書き認識APIタスクをキューイングして:

      1. ユーザーエージェントが認識用手書き認識器を作成できない場合、各失敗理由に応じて新しい例外でprejectします:

      2. それ以外の場合:

        1. resultを新しいHandwritingRecognizer オブジェクトとします。

        2. resultに前のステップで生成したプラットフォーム依存の手書き認識器を結び付けます。

        3. resultactiveフラグを trueにします。

        4. 解決する presult で。

  4. pを返します

5. 認識器の使用

const drawingHints = { textContext: "Hello world." }
const drawing = recognizer.startDrawing(textContext)

// \`drawing\` で何か処理を行う。
// 認識器に関連付けられたリソースを解放する。
recognizer.finish()

5.1. HandwritingRecognizer オブジェクト

[Exposed=Window, SecureContext]
interface HandwritingRecognizer {
  HandwritingDrawing startDrawing(optional HandwritingHints hints = {});

  undefined finish();
};

dictionary HandwritingHints {
  DOMString recognitionType = "text";
  DOMString inputType = "mouse";
  DOMString textContext;
  unsigned long alternatives = 3;
};

HandwritingRecognizer にはactiveフラグ(boolean)があり、初期値はtruefinish() メソッドが呼ばれるとfalseになります。

認識器のactiveフラグがtrueの間、Webアプリはこの認識器に新しい描画を関連付けて 認識処理を実行できます。

ユーザーエージェントは、ひとつのサイトで保持できるactive手書き認識器の総数を制限する場合があります。

5.2. startDrawing(hints)

このメソッドは、以降の認識のための描画情報を保存するHandwritingDrawing を作成します。

HandwritingDrawingstrokesリスト。初期値は空)と、それを構成するHandwritingStroke群を持ちます。

HandwritingDrawingrecognizerというフィールドで、このHandwritingDrawing を作成したHandwritingRecognizer を参照します。

startDrawing(hints) が呼ばれたときは、次のようにします:
  1. もし this.active フラグが true でない場合、新しい DOMException オブジェクトをスローし、その name メンバーを "InvalidStateError" にして中止する。

  2. 提供された hints を適した形式に変換する手書き認識器 に対して。

  3. 新しい HandwritingDrawingresult として作成し、必要であれば変換したヒントをそこに格納する。

  4. Set result.recognizerthis に設定する。

  5. this.strokes を新しい空の list に設定する。

  6. result を返す。

渡されたhintsに対応しないフィーチャが含まれている場合、ユーザーエージェントは該当属性を無視するべきです。

ヒントが省略された場合、ユーザーエージェントは任意のデフォルト値を適用してよいです。

ユーザーエージェントは、変換したhints手書き認識器の描画オブジェクトに直接渡すことも考えられます(HandwritingDrawing内に保存しなくてもよい)。

5.3. finish()

このメソッドはthisactiveフラグをfalseにし、割り当てられた手書き認識器リソースを解放し、 thisの今後の操作を失敗させます。

  1. thisactivetrueでなければ何もしない。

  2. thisactivefalseにする。

ユーザーエージェントは、手書き認識器に関連付いたリソースを解放すべきです。

finish()呼び出し以降、getPrediction() を本認識器作成のHandwritingDrawing で呼び出しても失敗します。

6. HandwritingDrawingの構築

HandwritingDrawing は描画に関するコンテキスト情報保持と、構成するストローク・ポイント群の管理を行います。これは描画そのものを表します。

ユーザーエージェントは、全ストロークとポイントをメモリ上に一旦保持し、getPrediction() 呼び出し時に手書き認識器向け形式に変換して利用してもよいです。この場合、HandwritingDrawing およびHandwritingStroke はリストの役割を果たします。

あるいは、ユーザーエージェントはストロークおよびポイントごと即座に認識器向き形式に変換し、HandwritingStrokeHandwritingDrawing のメソッド呼び出しタイミングでそれらを手書き認識器に渡す方法でもかまいません。

この場合、HandwritingDrawingHandwritingStroke はプラットフォーム依存オブジェクトのラッパー的存在となります。

ユーザーエージェントは、関連メソッド呼び出し時にストロークへ“修正あり”マークを付けて変更追跡(change tracking)を行うことで、getPrediction() のパフォーマンス向上を図ることができます。これにより、対応する手書き認識器でインクリメンタルな認識処理も可能となります。

例:3段落からなる描画があり、前回getPrediction() の予測が保存されています。この後3段落目にストローク追加があると、変更追跡あり実装ならその段落(や付近のストローク)に対し新たな認識リクエストと、既存結果と統合した返却が可能です。

const handwritingStroke = new HandwritingStroke()

// ストロークへポイントを追加
handwritingStroke.addPoint({ x: 1, y: 2, t: 0});
handwritingStroke.addPoint({ x: 7, y: 6, t: 33});

// このストロークの全てのポイントを取得
// 返却はコピー。返却値を変更してもストローク本体に影響しない。
const points = handwritingStroke.getPoints();

[ { x: 1:, t:2, t: 0 }, { x: 7, y: 6, t: 33} ];

// ストローク中の全ポイント消去
handwritingStroke.clear();

// 描画にストロークを追加
drawing.addStroke(handwritingStroke);

// 描画内ストロークすべてを取得
// 返却は HandwritingStroke のリスト。Webアプリで
// たとえば HandwritingStroke.addPoint() などによるストローク修正も可能。
drawing.getStrokes();

[ HandwritingStroke, /* ... */ ]

// 描画から特定ストローク削除
drawing.removeStroke(handwritingStroke);

// 描画から全ストローク削除
drawing.clear();
[Exposed=Window, SecureContext]
interface HandwritingDrawing {
  undefined addStroke(HandwritingStroke stroke);
  undefined removeStroke(HandwritingStroke stroke);
  undefined clear();
  sequence<HandwritingStroke> getStrokes();

  Promise<sequence<HandwritingPrediction>> getPrediction();
};

[SecureContext, Exposed=Window]
interface HandwritingStroke {
  constructor();
  undefined addPoint(HandwritingPoint point);
  sequence<HandwritingPoint> getPoints();
  undefined clear();
};

dictionary HandwritingPoint {
  required double x;
  required double y;

  // 任意。描画の基準時点からの経過ミリ秒数。
  DOMHighResTimeStamp t;
};
Webアプリが tHandwritingPoint で渡す場合は、 HandwritingDrawing 毎に全 t の起点を揃えてください。

例:startDrawing() 呼び出し時点を t === 0 としたり、各ポイント取得時に Date.now()(例:touchmove イベント発生時)を使ってもよいです。

6.1. HandwritingStroke

HandwritingStrokeストロークを表します。1つの動きを再現するのに必要な情報を保持します。

HandwritingStrokePointsを持ち、これはこのストロークのリストポイントを格納します。points は初期状態では空です。

6.1.1. HandwritingStroke()

  1. 新しいHandwritingStroke オブジェクトを作成し、resultとする。

  2. resultpointsを空のリストに設定する。

  3. resultを返す。

6.1.2. addPoint(point)

このメソッドはthisポイントを追加します。呼び出された際、以下を実行します:
  1. pointxメンバーがなければ、TypeErrorをスローし中止。

  2. point.xが数値でなければ、TypeErrorをスローし中止。

  3. pointyメンバーがなければ、TypeErrorをスローし中止。

  4. point.yが数値でなければ、TypeErrorをスローし中止。

  5. pointtメンバーがあり、それが数値でなければ、TypeErrorをスローし中止。

  6. pという新しいオブジェクトを作成する。

  7. p.xpoint.xを設定する。

  8. p.ypoint.yを設定する。

  9. pointtがあれば、p.tpoint.tを設定する。

  10. pthispoints追加する。

pointtがない場合、デフォルト値・補間数値等は利用せず、p.tが未設定であることを保持します。

addPoint(point) 呼び出し後にpointを変更しても、その後のHandwritingStrokeに影響しません。

6.1.3. getPoints()

このメソッドは、このストローク内のポイントを返します。

このメソッドが呼び出されたとき:
  1. result を新しい空の リスト とする

  2. すべての points について p として

    1. object の新しいインスタンスを pt として作成する

    2. pt.x メンバーに p.x をセット

    3. pt.y メンバーに p.y をセット

    4. pt メンバーがある場合は pt.tp.t をセット

    5. ptresult に追加

  3. result を返す

ディープコピーにより内部の points への変更を防ぎ、変更追跡を可能にします。

getPoints() の返り値を変更してもストロークには影響しません。

6.1.4. clear()

このメソッドは、このストロークのすべてのポイントを削除し、このストロークを空にします。

このメソッドが呼び出されたとき、
  1. this.points を空にする。

6.2. HandwritingDrawing

6.2.1. addStroke(stroke)

  1. strokeHandwritingStroke のインスタンスでない場合、TypeErrorをスローし中断。

  2. stroke への参照を this.strokes に追加する。

6.2.2. removeStroke(stroke)

  1. strokeHandwritingStroke のインスタンスでない場合、TypeErrorをスローし中断。

  2. this.strokes から アイテムが stroke と同一オブジェクトの場合に削除する。

6.2.3. getStrokes()

このメソッドは、この描画内のストローク一覧を返します。

このメソッドが呼び出されたとき、
  1. result を新しい空の リスト とする

  2. すべての strokessとして

    1. sresult に追加

  3. result を返す

6.2.4. clear()

  1. this.strokes を空にする。

7. HandwritingDrawingの予測を取得

// この描画内のストロークに対する予測を取得
const predictions = await drawing.getPrediction();

// \`predictions\`は\`HandwritingPrediction\`のリストで、属性は
// 認識器の機能やqueryHandwritingRecognizer()のモデル記述に依存。
//
// 例えばrecognizerがtextSegmentationをサポートする場合:
[
  {
    text: "hello",
    segmentationResult: [
      { grapheme: "h", beginIndex: "0", endIndex: "1",
        drawingSegments: [
          { strokeIndex: 1, beginPointIndex: 0, endPointIndex: 32 },
          { strokeIndex: 2 , beginPointIndex: 0, endPointIndex:: 40 },
        ]
      },
      {
        grapheme: "2", beginIndex: "1", endIndex: "2",
        drawingSegments: [
          { strokeIndex: 2 , beginPointIndex: 41, endPointIndex:: 130 },
        ]
      },
      // ...
    ]
  },
  {
    text: "he11o", segmentationResult: [ /* ... */ ]
  },
  // startDrawing()で指定したalternatives個まで
];

7.1. getPrediction()

getPrediction() メソッドは this 描画の予測リストとそのメタデータを返します。

予測は信頼度の高い順で並び、空でなければ最初の予測が最もありそうな結果です。

手書き認識器が何も認識できなかった場合、getPrediction() は空の リスト で解決されるべきです。

ユーザーエージェントは 変更追跡 を用いてインクリメンタル認識を行い、パフォーマンスを向上させる場合があります。

getPrediction() が呼ばれたとき:
  1. this.recognizer.active がtrueでなければ "InvalidStateError" DOMException でrejectされたpromise を返す。

  2. this.strokes が空なら新しい空のリストで解決されるpromise を返す。

  3. this の描画を手書き認識器向け形式へ変換 する。

  4. p を新しいPromiseとし、次のステップを 並列で実行:

    1. 変換した描画を手書き認識器に渡す。

    2. 手書き認識器が予測を返すのを待つ。

    3. 手書き認識APIタスクとして以下を実行:

      1. result をリストとして用意。

      2. 予測 pred それぞれについて

        1. pred を変換する HandwritingPrediction idl_pred.

        2. idl_predresult に追加。

      3. presult で解決。

  5. p を返す

7.2. HandwritingPrediction 属性

HandwritingPrediction手書き認識器からの予測結果を表します。

dictionary HandwritingPrediction {
  required DOMString text;
  sequence<HandwritingSegment> segmentationResult;
};

dictionary HandwritingSegment {
  required DOMString grapheme;
  required unsigned long beginIndex;
  required unsigned long endIndex;
  required sequence<HandwritingDrawingSegment> drawingSegments;
};

dictionary HandwritingDrawingSegment {
  required unsigned long strokeIndex;
  required unsigned long beginPointIndex;
  required unsigned long endPointIndex;
};
text
描画の転写を表す DOMString
segmentationResult
各認識済みのグラフェム(ユーザーが知覚する文字)と、その構成ストロークとポイントの対応を示す HandwritingSegment のリスト。

手書き認識器がテキストのセグメンテーション をサポートしない場合は null となります。

Webアプリケーションは textSegmentation でこの属性がnullになりうるか判別できます。

7.2.1. HandwritingSegment 属性

HandwritingSegment は描画からセグメント化された1つのグラフェムについて記述します。

grapheme
グラフェムを表す DOMString
beginIndex
text 内でこのグラフェムが始まるインデックス。
endIndex
text 内でこのグラフェムが終わる(次のグラフェムが始まる)インデックス。
drawingSegments
このグラフェムを構成する描画部分を記述する HandwritingDrawingSegment のリスト。

textbeginIndexendIndex でスライスすると、grapheme になります。

// Webアプリケーションは `beginIndex` と `endIndex` で `text` をスライスできます。
// 例: "घोषित" の `HandwritingPrediction`

const prediction = {
  // UTF-16コードポイント: \u0918 \u094b \u0937 \u093f \u0924
  // グラフェム: घो, षि, त
  text: "घोषित",
  segmentationResult: [
    { grapheme: "घो", beginIndex: "0", endIndex: "2" },
    { grapheme: "षि", beginIndex: "2", endIndex: "4" },
    { grapheme: "त", beginIndex: "4", endIndex: "5" },
  ]
}

// 次のようになる:
prediction.text.slice(0, 1) === "घो";
prediction.text.slice(2, 4) === "षि";
prediction.text.slice(4, 5) === "त";

// 2番目のグラフェム (षि) はspliceで削除できる
const withoutSecondGrapheme = (
  [...prediction.text]
    .splice(
      prediction.segmentationResult[1].beginIndex,
      prediction.segmentationResult[1].endIndex
    )
    .join('')
);
// => "घोत"

7.2.2. HandwritingDrawingSegment 属性

HandwritingDrawingSegmentHandwritingStroke の連続領域を表します。

各属性は HandwritingStrokeHandwritingDrawinggetPrediction() された時点に基づきます。

strokeIndex
HandwritingDrawing.strokes 内の HandwritingStroke のインデックス。
beginIndex
描画セグメントの開始インデックス。
endIndex
描画セグメントの終了インデックス(次の描画セグメントの開始点)。

8. プライバシーに関する考慮事項

このセクションは規範的ではありません。

フィンガープリントベクターは、フィーチャー検出と認識器の実装という2つの部分から発生します。

公開される情報量(エントロピー)はユーザーエージェントの実装に依存します。一律の解決策はないと考えるため、必要に応じてプライバシー保護(例:許可プロンプト)を適用するかはユーザーエージェントの判断を推奨します。

フィーチャー検出 で以下の情報が漏れる可能性があります:

フィンガープリント対策としては以下が考えられます:

認識器の実装 もOS、デバイスやユーザーの習慣に関する情報を露呈する可能性があります。これは使用される認識器技術に大きく依存します。

下記は実装の種類とそのリスクです:

ただしこのタイプの実装があることは現在把握していません。この種のモデルを使用する場合は必ずプライバシー対策や、セッション毎クリアな状態の使用を推奨します。

フィンガープリントのコスト:モデル差異を活用するため、フィンガープリント手法は手書き(敵対例)サンプル一式を作成・管理するコストを要します。負担は大きい可能性がありますが、本気で取り組めばサンプルを取得できると考えてよいでしょう。

索引

この仕様で定義されている用語

参照によって定義される用語

参考文献

規範的参照

[BCP47]
A. Phillips, Ed.; M. Davis, Ed.. Tags for Identifying Languages. September 2009. Best Current Practice. URL: https://www.rfc-editor.org/rfc/rfc5646
[ECMASCRIPT]
ECMAScript Language Specification. URL: https://tc39.es/ecma262/multipage/
[HR-TIME-3]
Yoav Weiss. High Resolution Time. URL: https://w3c.github.io/hr-time/
[HTML]
Anne van Kesteren; et al. HTML Standard. Living Standard. URL: https://html.spec.whatwg.org/multipage/
[INFRA]
Anne van Kesteren; Domenic Denicola. Infra Standard. Living Standard. URL: https://infra.spec.whatwg.org/
[WEBIDL]
Edgar Chen; Timothy Gu. Web IDL Standard. Living Standard. URL: https://webidl.spec.whatwg.org/

IDL索引

[SecureContext]
partial interface Navigator {
  Promise<HandwritingRecognizerQueryResult?>
      queryHandwritingRecognizer(HandwritingModelConstraint constraint);
};

dictionary HandwritingModelConstraint {
  required sequence<DOMString> languages;
};

dictionary HandwritingRecognizerQueryResult {
  boolean textAlternatives;
  boolean textSegmentation;
  HandwritingHintsQueryResult hints;
};

dictionary HandwritingHintsQueryResult {
  sequence<HandwritingRecognitionType> recognitionType;
  sequence<HandwritingInputType> inputType;
  boolean textContext;
  boolean alternatives;
};

enum HandwritingRecognitionType{
  "text", "per-character"
};

enum HandwritingInputType {
  "mouse", "stylus", "touch"
};

[SecureContext]
partial interface Navigator {
  Promise<HandwritingRecognizer>
      createHandwritingRecognizer(HandwritingModelConstraint constraint);
};

[Exposed=Window, SecureContext]
interface HandwritingRecognizer {
  HandwritingDrawing startDrawing(optional HandwritingHints hints = {});

  undefined finish();
};

dictionary HandwritingHints {
  DOMString recognitionType = "text";
  DOMString inputType = "mouse";
  DOMString textContext;
  unsigned long alternatives = 3;
};

[Exposed=Window, SecureContext]
interface HandwritingDrawing {
  undefined addStroke(HandwritingStroke stroke);
  undefined removeStroke(HandwritingStroke stroke);
  undefined clear();
  sequence<HandwritingStroke> getStrokes();

  Promise<sequence<HandwritingPrediction>> getPrediction();
};

[SecureContext, Exposed=Window]
interface HandwritingStroke {
  constructor();
  undefined addPoint(HandwritingPoint point);
  sequence<HandwritingPoint> getPoints();
  undefined clear();
};

dictionary HandwritingPoint {
  required double x;
  required double y;

  // Optional. Number of milliseconds since a reference time point for a
  // drawing.
  DOMHighResTimeStamp t;
};

dictionary HandwritingPrediction {
  required DOMString text;
  sequence<HandwritingSegment> segmentationResult;
};

dictionary HandwritingSegment {
  required DOMString grapheme;
  required unsigned long beginIndex;
  required unsigned long endIndex;
  required sequence<HandwritingDrawingSegment> drawingSegments;
};

dictionary HandwritingDrawingSegment {
  required unsigned long strokeIndex;
  required unsigned long beginPointIndex;
  required unsigned long endPointIndex;
};