Handwriting Recognition API memungkinkan Anda mengenali teks dari input tulisan tangan saat input tersebut dibuat.
Apa yang dimaksud dengan Handwriting Recognition API?
Handwriting Recognition API memungkinkan Anda mengonversi tulisan tangan (tinta) dari pengguna menjadi teks. Beberapa sistem operasi telah lama menyertakan API tersebut, dan dengan kemampuan baru ini, aplikasi web Anda akhirnya dapat menggunakan fungsi ini. Konversi terjadi langsung di perangkat pengguna, bahkan berfungsi dalam mode offline, semuanya tanpa menambahkan library atau layanan pihak ketiga.
API ini menerapkan pengenalan yang disebut "online" atau hampir real-time. Artinya, input tulisan tangan dikenali saat pengguna menggambarnya dengan mengambil dan menganalisis goresan tunggal. Berbeda dengan prosedur "offline" seperti Optical Character Recognition (OCR), yang hanya mengetahui produk akhir, algoritma online dapat memberikan tingkat akurasi yang lebih tinggi karena sinyal tambahan seperti urutan temporal dan tekanan setiap goresan tinta.
Kasus penggunaan yang disarankan untuk Handwriting Recognition API
Contoh penggunaannya meliputi:
- Aplikasi pencatat yang memungkinkan pengguna mengambil catatan tulisan tangan dan menerjemahkannya menjadi teks.
- Aplikasi formulir tempat pengguna dapat menggunakan input pena atau jari karena keterbatasan waktu.
- Game yang mengharuskan pemain mengisi huruf atau angka, seperti teka-teki silang, hangman, atau sudoku.
Status saat ini
Handwriting Recognition API tersedia dari (Chromium 99).
Cara menggunakan Handwriting Recognition API
Deteksi fitur
Deteksi dukungan browser dengan memeriksa keberadaan metode createHandwritingRecognizer()
di objek navigator:
if ('createHandwritingRecognizer' in navigator) {
// 🎉 The Handwriting Recognition API is supported!
}
Konsep inti
Handwriting Recognition API mengonversi input tulisan tangan menjadi teks, apa pun metode inputnya (mouse, sentuh, pena). API ini memiliki empat entity utama:
- Titik mewakili posisi pointer pada waktu tertentu.
- Goresan terdiri dari satu atau beberapa titik. Perekaman goresan dimulai saat pengguna meletakkan kursor (yaitu, mengklik tombol mouse utama, atau menyentuh layar dengan pena atau jari) dan berakhir saat mereka mengangkat kursor kembali.
- Gambar terdiri dari satu atau beberapa goresan. Pengenalan sebenarnya terjadi di tingkat ini.
- Pengenal dikonfigurasi dengan bahasa input yang diharapkan. Ini digunakan untuk membuat instance gambar dengan konfigurasi pengenal yang diterapkan.
Konsep ini diterapkan sebagai antarmuka dan kamus tertentu, yang akan segera saya bahas.
Membuat pengenal
Untuk mengenali teks dari input tulisan tangan, Anda perlu mendapatkan instance
HandwritingRecognizer
dengan memanggil navigator.createHandwritingRecognizer()
dan meneruskan batasan
kepadanya. Batasan menentukan model pengenalan tulisan tangan yang harus digunakan. Saat ini, Anda
dapat menentukan daftar bahasa dalam urutan preferensi:
const recognizer = await navigator.createHandwritingRecognizer({
languages: ['en'],
});
Metode ini menampilkan promise yang diselesaikan dengan instance HandwritingRecognizer
saat browser dapat memenuhi permintaan Anda. Jika tidak, promise akan ditolak dengan error, dan
pengenalan tulisan tangan tidak akan tersedia. Oleh karena itu, sebaiknya Anda membuat kueri
dukungan pengenal untuk fitur pengenalan tertentu terlebih dahulu.
Dukungan pengenal kueri
Dengan memanggil navigator.queryHandwritingRecognizerSupport()
, Anda dapat memeriksa apakah platform target
mendukung fitur pengenalan tulisan tangan yang ingin Anda gunakan. Pada contoh berikut, developer:
- ingin mendeteksi teks dalam bahasa Inggris
- mendapatkan prediksi alternatif yang kurang mungkin jika tersedia
- mendapatkan akses ke hasil segmentasi, yaitu karakter yang dikenali, termasuk titik dan goresan
const { languages, alternatives, segmentationResults } =
await navigator.queryHandwritingRecognizerSupport({
languages: ['en'],
alternatives: true,
segmentationResult: true,
});
console.log(languages); // true or false
console.log(alternatives); // true or false
console.log(segmentationResult); // true or false
Metode ini menampilkan promise yang diselesaikan dengan objek hasil. Jika browser mendukung fitur
yang ditetapkan oleh developer, nilainya akan ditetapkan ke true
. Jika tidak, nilai ini akan ditetapkan ke false
.
Anda dapat menggunakan informasi ini untuk mengaktifkan atau menonaktifkan fitur tertentu dalam aplikasi, atau untuk menyesuaikan kueri dan mengirim kueri baru.
Memulai gambar
Dalam aplikasi, Anda harus menawarkan area input tempat pengguna membuat entri tulisan tangan. Karena alasan performa, sebaiknya terapkan cara ini dengan bantuan objek kanvas. Penerapan sebenarnya dari bagian ini berada di luar cakupan artikel ini, tetapi Anda dapat membaca demo untuk mengetahui cara melakukannya.
Untuk memulai gambar baru, panggil metode startDrawing()
pada pengenal. Metode ini mengambil
objek yang berisi petunjuk yang berbeda untuk menyesuaikan algoritma pengenalan. Semua petunjuk bersifat opsional:
- Jenis teks yang dimasukkan: teks, alamat email, angka, atau karakter individual
(
recognitionType
) - Jenis perangkat input: input mouse, sentuh, atau pena (
inputType
) - Teks sebelumnya (
textContext
) - Jumlah prediksi alternatif yang kurang mungkin yang harus ditampilkan (
alternatives
) - Daftar karakter yang dapat diidentifikasi pengguna ("grafem") yang kemungkinan besar akan dimasukkan pengguna
(
graphemeSet
)
Handwriting Recognition API berfungsi dengan baik dengan
Pointer Events yang menyediakan
antarmuka abstrak untuk menggunakan input dari perangkat penunjuk apa pun. Argumen peristiwa pointer berisi
jenis pointer yang digunakan. Artinya, Anda dapat menggunakan peristiwa pointer untuk menentukan jenis input
secara otomatis. Pada contoh berikut, gambar untuk pengenalan tulisan tangan otomatis
dibuat pada kemunculan pertama peristiwa pointerdown
di area tulisan tangan. Karena
pointerType
mungkin kosong atau ditetapkan ke nilai eksklusif, saya memperkenalkan pemeriksaan konsistensi untuk memastikan
hanya nilai yang didukung yang ditetapkan untuk jenis input gambar.
let drawing;
let activeStroke;
canvas.addEventListener('pointerdown', (event) => {
if (!drawing) {
drawing = recognizer.startDrawing({
recognitionType: 'text', // email, number, per-character
inputType: ['mouse', 'touch', 'pen'].find((type) => type === event.pointerType),
textContext: 'Hello, ',
alternatives: 2,
graphemeSet: ['f', 'i', 'z', 'b', 'u'], // for a fizz buzz entry form
});
}
startStroke(event);
});
Menambahkan goresan
Peristiwa pointerdown
juga merupakan tempat yang tepat untuk memulai goresan baru. Untuk melakukannya, buat instance
HandwritingStroke
baru. Selain itu, Anda harus menyimpan waktu saat ini sebagai titik referensi untuk
titik berikutnya yang ditambahkan ke titik tersebut:
function startStroke(event) {
activeStroke = {
stroke: new HandwritingStroke(),
startTime: Date.now(),
};
addPoint(event);
}
Tambahkan titik
Setelah membuat goresan, Anda harus langsung menambahkan titik pertama ke goresan tersebut. Karena Anda akan menambahkan lebih banyak poin nantinya, sebaiknya terapkan logika pembuatan poin dalam metode terpisah. Dalam
contoh berikut, metode addPoint()
menghitung waktu yang berlalu dari stempel waktu referensi.
Informasi temporal bersifat opsional, tetapi dapat meningkatkan kualitas pengenalan. Kemudian, metode ini membaca koordinat X dan Y dari peristiwa pointer dan menambahkan titik ke goresan saat ini.
function addPoint(event) {
const timeElapsed = Date.now() - activeStroke.startTime;
activeStroke.stroke.addPoint({
x: event.offsetX,
y: event.offsetY,
t: timeElapsed,
});
}
Pengendali peristiwa pointermove
dipanggil saat pointer dipindahkan di layar. Titik-titik tersebut juga perlu ditambahkan ke {i>stroke<i}. Peristiwa ini juga dapat dinaikkan jika pointer tidak dalam
status "bawah", misalnya saat menggerakkan kursor melintasi layar tanpa menekan tombol
mouse. Pengendali peristiwa dari contoh berikut memeriksa apakah goresan aktif ada, dan menambahkan
titik baru ke dalamnya.
canvas.addEventListener('pointermove', (event) => {
if (activeStroke) {
addPoint(event);
}
});
Mengenali teks
Saat pengguna mengangkat kursor lagi, Anda dapat menambahkan goresan ke gambar dengan memanggil
metode addStroke()
-nya. Contoh berikut juga mereset activeStroke
, sehingga pengendali
pointermove
tidak akan menambahkan titik ke goresan yang telah selesai.
Selanjutnya, saatnya mengenali input pengguna dengan memanggil metode getPrediction()
pada
gambar. Pengenalan biasanya memerlukan waktu kurang dari beberapa ratus milidetik, sehingga Anda dapat menjalankan prediksi berulang kali jika diperlukan. Contoh berikut menjalankan prediksi baru setelah setiap goresan selesai.
canvas.addEventListener('pointerup', async (event) => {
drawing.addStroke(activeStroke.stroke);
activeStroke = null;
const [mostLikelyPrediction, ...lessLikelyAlternatives] = await drawing.getPrediction();
if (mostLikelyPrediction) {
console.log(mostLikelyPrediction.text);
}
lessLikelyAlternatives?.forEach((alternative) => console.log(alternative.text));
});
Metode ini menampilkan promise yang diselesaikan dengan array prediksi yang diurutkan berdasarkan kemungkinannya. Jumlah elemen bergantung pada nilai yang Anda teruskan ke petunjuk alternatives
. Anda
dapat menggunakan array ini untuk menampilkan pilihan kemungkinan kecocokan kepada pengguna, dan meminta mereka memilih
opsi. Atau, Anda dapat menggunakan prediksi yang paling mungkin, seperti yang saya lakukan dalam
contoh.
Objek prediksi berisi teks yang dikenali dan hasil segmentasi opsional, yang akan saya bahas di bagian berikut.
Insight terperinci dengan hasil segmentasi
Jika didukung oleh platform target, objek prediksi juga dapat berisi hasil segmentasi.
Ini adalah array yang berisi semua segmen tulisan tangan yang dikenali, kombinasi karakter yang dikenali
dan dapat diidentifikasi pengguna (grapheme
) beserta posisinya dalam teks yang dikenali
(beginIndex
, endIndex
), serta goresan dan titik yang membuatnya.
if (mostLikelyPrediction.segmentationResult) {
mostLikelyPrediction.segmentationResult.forEach(
({ grapheme, beginIndex, endIndex, drawingSegments }) => {
console.log(grapheme, beginIndex, endIndex);
drawingSegments.forEach(({ strokeIndex, beginPointIndex, endPointIndex }) => {
console.log(strokeIndex, beginPointIndex, endPointIndex);
});
},
);
}
Anda dapat menggunakan informasi ini untuk melacak kembali grafem yang dikenali di kanvas.
Menyelesaikan pengakuan
Setelah pengenalan selesai, Anda dapat mengosongkan resource dengan memanggil metode clear()
di
HandwritingDrawing
, dan metode finish()
di HandwritingRecognizer
:
drawing.clear();
recognizer.finish();
Demo
Komponen web <handwriting-textarea>
mengimplementasikan kontrol pengeditan yang ditingkatkan secara bertahap yang mampu mengenali tulisan tangan. Dengan mengklik tombol di pojok kanan bawah kontrol pengeditan, Anda akan mengaktifkan
mode menggambar. Setelah Anda menyelesaikan gambar, komponen web akan otomatis memulai
pengenalan dan menambahkan kembali teks yang dikenali ke kontrol pengeditan. Jika Handwriting Recognition
API tidak didukung sama sekali, atau platform tidak mendukung fitur yang diminta, tombol edit
akan disembunyikan. Namun, kontrol pengeditan dasar tetap dapat digunakan sebagai <textarea>
.
Komponen web menawarkan properti dan atribut untuk menentukan perilaku pengenalan dari
luar, termasuk languages
dan recognitiontype
. Anda dapat menetapkan konten kontrol melalui
atribut value
:
<handwriting-textarea languages="en" recognitiontype="text" value="Hello"></handwriting-textarea>
Untuk mendapatkan informasi tentang perubahan nilai, Anda dapat memproses peristiwa input
.
Anda dapat mencoba komponen menggunakan demo ini di Glitch. Selain itu, pastikan untuk melihat kode sumber. Untuk menggunakan kontrol di aplikasi Anda, dapatkan dari npm.
Keamanan dan izin
Tim Chromium mendesain dan menerapkan Handwriting Recognition API menggunakan prinsip inti yang ditentukan dalam Mengontrol Akses ke Fitur Platform Web yang Andal, termasuk kontrol pengguna, transparansi, dan ergonomi.
Kontrol pengguna
Handwriting Recognition API tidak dapat dinonaktifkan oleh pengguna. Fitur ini hanya tersedia untuk situs yang dikirimkan melalui HTTPS, dan hanya dapat dipanggil dari konteks penjelajahan tingkat atas.
Transparansi
Tidak ada indikasi apakah pengenalan tulisan tangan aktif. Untuk mencegah pembuatan sidik jari, browser menerapkan tindakan pencegahan, seperti menampilkan permintaan izin kepada pengguna saat mendeteksi kemungkinan penyalahgunaan.
Persistensi izin
Handwriting Recognition API saat ini tidak menampilkan perintah izin apa pun. Dengan demikian, izin tidak perlu dipertahankan dengan cara apa pun.
Masukan
Tim Chromium ingin mengetahui pengalaman Anda saat menggunakan Handwriting Recognition API.
Ceritakan kepada kami tentang desain API
Apakah ada sesuatu tentang API yang tidak berfungsi seperti yang Anda harapkan? Atau apakah ada metode atau properti yang tidak ada yang Anda perlukan untuk menerapkan ide Anda? Ada pertanyaan atau komentar tentang model keamanan? Ajukan masalah spesifikasi di repo GitHub yang sesuai, atau tambahkan pendapat Anda ke masalah yang sudah ada.
Melaporkan masalah terkait penerapan
Apakah Anda menemukan bug pada penerapan Chromium? Atau apakah implementasinya berbeda dengan spesifikasi?
Laporkan bug di new.crbug.com. Pastikan untuk menyertakan detail sebanyak mungkin,
petunjuk sederhana untuk mereproduksi, dan masukkan Blink>Handwriting
di kotak Components.
Glitch sangat cocok untuk membagikan rekaman ulang yang cepat dan mudah.
Menampilkan dukungan untuk API
Apakah Anda berencana menggunakan Handwriting Recognition API? Dukungan publik Anda membantu tim Chromium memprioritaskan fitur dan menunjukkan kepada vendor browser lain betapa pentingnya mendukung fitur tersebut.
Bagikan rencana penggunaannya di rangkaian pesan Discourse WICG. Kirim tweet ke
@ChromiumDev menggunakan hashtag
#HandwritingRecognition
dan beri tahu kami tempat dan cara Anda menggunakannya.
Tautan Bermanfaat
- Penjelas
- Draf spesifikasi
- Repositori GitHub
- ChromeStatus
- Bug Chromium
- Peninjauan TAG
- Niat untuk Membuat Prototipe
- Thread WebKit-Dev
- Posisi standar Mozilla
Ucapan terima kasih
Dokumen ini telah ditinjau oleh Joe Medley, Honglin Yu, dan Jiewei Qian.