Handwriting Recognition API memungkinkan Anda mengenali teks dari input tulisan tangan saat teks tersebut ditulis.
Apa itu 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, berfungsi bahkan dalam mode offline, semuanya tanpa menambahkan library atau layanan pihak ketiga.
API ini menerapkan pengenalan "online" atau hampir real-time. Artinya, input tulisan tangan dikenali saat pengguna menggambarnya dengan merekam dan menganalisis goresan tunggal. Berbeda dengan prosedur "offline" seperti Optical Character Recognition (OCR), yang hanya diketahui produk akhirnya, 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 penggunaan mencakup:
- Aplikasi pencatatan yang memungkinkan pengguna mengambil catatan tulisan tangan dan menerjemahkannya menjadi teks.
- Aplikasi formulir tempat pengguna dapat menggunakan input stilus atau jari karena batasan waktu.
- Game yang mengharuskan pengisian huruf atau angka, seperti teka-teki silang, hangman, atau sudoku.
Status saat ini
Handwriting Recognition API tersedia mulai dari (Chromium 99).
Cara menggunakan Handwriting Recognition API
Deteksi fitur
Deteksi dukungan browser dengan memeriksa keberadaan metode createHandwritingRecognizer()
pada objek navigator:
if ('createHandwritingRecognizer' in navigator) {
// 🎉 The Handwriting Recognition API is supported!
}
Konsep inti
Handwriting Recognition API mengonversi input tulisan tangan menjadi teks, terlepas dari metode inputnya (mouse, sentuhan, stilus). API ini memiliki empat entitas utama:
- Titik menunjukkan posisi pointer pada waktu tertentu.
- Goresan terdiri dari satu atau beberapa titik. Perekaman goresan dimulai saat pengguna meletakkan pointer (yaitu, mengklik tombol mouse utama, atau menyentuh layar dengan stylus atau jari) dan berakhir saat mereka mengangkat pointer kembali.
- Gambar terdiri dari satu atau beberapa goresan. Pengenalan sebenarnya terjadi di tingkat ini.
- Pengenal dikonfigurasi dengan bahasa input yang diharapkan. Objek ini digunakan untuk membuat instance gambar dengan konfigurasi pengenal yang diterapkan.
Konsep ini diimplementasikan sebagai antarmuka dan kamus tertentu, yang akan saya bahas sebentar lagi.
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 kueri dukungan pengenal untuk fitur pengenalan tertentu terlebih dahulu.
Mengueri dukungan pengenal
Dengan memanggil navigator.queryHandwritingRecognizer()
, Anda dapat memeriksa apakah platform target mendukung fitur pengenalan tulisan tangan yang ingin Anda gunakan. Metode ini mengambil
objek batasan yang sama dengan metode navigator.createHandwritingRecognizer()
,
yang berisi daftar bahasa yang diminta. Metode ini menampilkan promise yang diselesaikan dengan objek hasil jika pengenal yang kompatibel ditemukan. Jika tidak, promise akan diselesaikan ke null
.
Dalam contoh berikut, developer:
- ingin mendeteksi teks dalam bahasa Inggris
- mendapatkan prediksi alternatif yang lebih kecil kemungkinannya jika tersedia
- mendapatkan akses ke hasil segmentasi, yaitu karakter yang dikenali, termasuk titik dan goresan yang membentuknya
const result =
await navigator.queryHandwritingRecognizerSupport({
languages: ['en']
});
console.log(result?.textAlternatives); // true if alternatives are supported
console.log(result?.textSegmentation); // true if segmentation is supported
Jika browser mendukung fitur
yang diperlukan oleh developer, nilainya akan ditetapkan ke true
dalam objek hasil. Jika tidak, nilai ini akan ditetapkan ke false
.
Anda dapat menggunakan informasi ini untuk mengaktifkan atau menonaktifkan fitur tertentu dalam aplikasi atau mengirim kueri baru untuk kumpulan bahasa yang berbeda.
Mulai menggambar
Dalam aplikasi, Anda harus menyediakan area input tempat pengguna membuat entri tulisan tangan. Untuk alasan performa, sebaiknya terapkan ini dengan bantuan objek kanvas. Penerapan yang tepat dari bagian ini berada di luar cakupan artikel ini, tetapi Anda dapat melihat demo untuk melihat cara melakukannya.
Untuk memulai gambar baru, panggil metode startDrawing()
pada pengenal. Metode ini mengambil objek yang berisi berbagai petunjuk 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 stilus (
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 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 penunjuk untuk menentukan jenis input secara otomatis. Pada contoh berikut, gambar untuk pengenalan tulisan tangan dibuat secara otomatis 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', 'stylus'].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 dalamnya:
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 titik nanti, sebaiknya terapkan logika pembuatan titik dalam metode terpisah. Dalam
contoh berikut, metode addPoint()
menghitung waktu yang telah berlalu dari stempel waktu referensi.
Informasi temporal bersifat opsional, tetapi dapat meningkatkan kualitas pengenalan. Kemudian, kode 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,
});
}
Handler peristiwa pointermove
dipanggil saat pointer dipindahkan di layar. Titik tersebut juga perlu ditambahkan ke goresan. Peristiwa juga dapat dimunculkan jika pointer tidak dalam status "turun", misalnya saat memindahkan kursor di layar tanpa menekan tombol mouse. Handler peristiwa dari contoh berikut memeriksa apakah ada goresan aktif, dan menambahkan
titik baru ke goresan tersebut.
canvas.addEventListener('pointermove', (event) => {
if (activeStroke) {
addPoint(event);
}
});
Mengenali teks
Saat pengguna mengangkat pointer lagi, Anda dapat menambahkan goresan ke gambar dengan memanggil metode
addStroke()
-nya. Contoh berikut juga mereset activeStroke
, sehingga pengendali pointermove
tidak akan menambahkan poin ke goresan yang 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 di-resolve dengan array prediksi yang diurutkan berdasarkan
kemungkinannya. Jumlah elemen bergantung pada nilai yang Anda teruskan ke petunjuk alternatives
. Anda
dapat menggunakan array ini untuk menyajikan pilihan kemungkinan kecocokan kepada pengguna, dan meminta mereka memilih
opsi. Atau, Anda dapat memilih 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 mendetail 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 dapat diidentifikasi pengguna yang dikenali (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.
Pengenalan lengkap
Setelah pengenalan selesai, Anda dapat membebaskan resource dengan memanggil metode clear()
di
HandwritingDrawing
, dan metode finish()
di HandwritingRecognizer
:
drawing.clear();
recognizer.finish();
Demo
Komponen web <handwriting-textarea>
menerapkan kontrol pengeditan yang ditingkatkan secara progresif dan mampu melakukan pengenalan tulisan tangan. Dengan mengklik tombol di sudut kanan bawah kontrol pengeditan, Anda mengaktifkan
mode menggambar. Saat 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 menyetel konten kontrol melalui atribut
value
:
<handwriting-textarea languages="en" recognitiontype="text" value="Hello"></handwriting-textarea>
Untuk mengetahui perubahan nilai, Anda dapat memproses peristiwa input
.
Anda dapat mencoba komponen menggunakan demo ini di GitHub. Pastikan juga 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 Canggih, termasuk kontrol pengguna, transparansi, dan ergonomi.
Kontrol pengguna
Handwriting Recognition API tidak dapat dinonaktifkan oleh pengguna. API ini hanya tersedia untuk situs yang ditayangkan melalui HTTPS, dan hanya dapat dipanggil dari konteks penjelajahan tingkat teratas.
Transparansi
Tidak ada indikasi apakah pengenalan tulisan tangan aktif. Untuk mencegah pembuatan sidik jari, browser menerapkan tindakan pencegahan, seperti menampilkan dialog izin kepada pengguna saat mendeteksi kemungkinan penyalahgunaan.
Persistensi izin
Handwriting Recognition API saat ini tidak menampilkan perintah izin apa pun. Oleh karena itu, izin tidak perlu dipertahankan dengan cara apa pun.
Masukan
Tim Chromium ingin mengetahui pengalaman Anda saat menggunakan Handwriting Recognition API.
Beri tahu 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 dan perlu Anda terapkan untuk mewujudkan ide Anda? Ada pertanyaan atau komentar tentang model keamanan? Laporkan 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 Komponen.
Menunjukkan 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 dukungan untuk fitur tersebut.
Bagikan rencana penggunaan Anda di thread WICG Discourse. Kirim tweet ke
@ChromiumDev menggunakan hashtag
#HandwritingRecognition
dan beri tahu kami di mana dan bagaimana Anda menggunakannya.
Tautan Bermanfaat
- Penjelasan
- Draf spesifikasi
- Repositori GitHub
- ChromeStatus
- Bug Chromium
- Ulasan TAG
- Maksud untuk Membuat Prototipe
- Thread WebKit-Dev
- Posisi standar Mozilla
Ucapan terima kasih
Dokumen ini ditinjau oleh Joe Medley, Honglin Yu, dan Jiewei Qian.