Pengenalan Tulis Tangan API memungkinkan Anda mengenali teks dari input tulisan tangan saat sedang aktif.
Apa itu Handwriting Recognition API?
Pengenalan Tulis Tangan 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 dapat akhirnya menggunakan fungsi ini. Konversi terjadi langsung di perangkat pengguna, berfungsi bahkan dalam mode offline, semuanya tanpa menambahkan perpustakaan atau layanan pihak ketiga apa pun.
API ini mengimplementasikan apa yang disebut "online" atau pengenalan hampir real-time. Ini berarti bahwa input tulisan tangan dikenali saat pengguna menggambarnya dengan menangkap dan menganalisis {i>stroke<i}. Berbeda dengan "off-line" prosedur seperti Pengenalan Karakter Optik (OCR), di mana hanya produk akhir yang diketahui, algoritma {i>online<i} 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 pembuatan catatan di mana pengguna ingin mengambil catatan tulisan tangan dan memintanya menjadi teks.
- Membentuk aplikasi yang memungkinkan pengguna menggunakan input pena atau jari karena keterbatasan waktu.
- Game yang mengharuskan pengisian 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()
pada 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 lokasi pointer pada waktu tertentu.
- Goresan terdiri dari satu atau beberapa titik. Perekaman {i>stroke<i} dimulai ketika pengguna meletakkan kursor ke bawah (yaitu, mengklik tombol {i>mouse<i} utama, atau menyentuh layar dengan pena mereka atau jari) dan berakhir saat mereka mengangkat pointer kembali ke atas.
- Gambar terdiri dari satu atau beberapa goresan. Pengenalan yang sebenarnya dilakukan di tingkat ini.
- Pengenalan dikonfigurasi dengan bahasa input yang diharapkan. Ini digunakan untuk membuat instance gambar dengan konfigurasi pengenal yang diterapkan.
Konsep ini diterapkan sebagai antarmuka dan kamus spesifik, 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
IP eksternal mana pun yang
ditetapkan pada instance tersebut. 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, sistem akan menolak promise dengan error, dan
pengenalan tulis tangan tidak akan tersedia. Untuk alasan ini, Anda mungkin ingin melakukan 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 tulis tangan yang ingin Anda gunakan. Pada contoh berikut,
pengembang:
- ingin mendeteksi pesan teks dalam bahasa Inggris
- mendapatkan prediksi alternatif yang lebih kecil jika tersedia
- mendapatkan akses ke hasil segmentasi, yaitu, karakter yang dikenali, termasuk poin dan {i>stroke<i} yang membentuknya
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 tersebut
ditentukan 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
sesuaikan kueri Anda dan kirimkan kueri baru.
Mulai menggambar
Di dalam aplikasi, Anda harus menyediakan area {i>input <i}yang mana pengguna membuat entri. Untuk alasan kinerja, disarankan untuk menerapkannya dengan bantuan objek kanvas. Persis penerapan 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 memerlukan
objek yang berisi petunjuk berbeda untuk menyesuaikan algoritma pengenalan. Semua petunjuk bersifat opsional:
- Jenis teks yang dimasukkan: teks, alamat email, angka, atau karakter tertentu
(
recognitionType
) - Jenis perangkat input: input mouse, sentuh, atau pena (
inputType
) - Teks sebelumnya (
textContext
) - Jumlah prediksi alternatif yang kurang mungkin dan harus ditampilkan (
alternatives
) - Daftar karakter yang dapat diidentifikasi pengguna ("grafik") yang kemungkinan besar akan dimasukkan pengguna
(
graphemeSet
)
Handwriting Recognition API cocok dengan
Peristiwa Pointer yang menyediakan
antarmuka abstrak untuk menggunakan input dari perangkat penunjuk apa pun. Argumen peristiwa pointer berisi
jenis {i>pointer<i} yang digunakan. Ini berarti Anda bisa menggunakan kejadian pointer untuk menentukan jenis input
secara otomatis. Dalam contoh berikut, gambar untuk pengenalan tulis tangan secara otomatis
dibuat saat peristiwa pointerdown
pertama terjadi di area tulisan tangan. Sebagai
pointerType
mungkin kosong atau ditetapkan ke nilai eksklusif, saya melakukan pemeriksaan konsistensi untuk
pastikan 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);
});
Tambahkan goresan
Peristiwa pointerdown
juga merupakan tempat yang tepat untuk memulai goresan baru. Untuk melakukannya, buat
dari instance HandwritingStroke
. Selain itu, Anda harus menyimpan waktu
saat ini sebagai titik referensi untuk
poin selanjutnya yang ditambahkan:
function startStroke(event) {
activeStroke = {
stroke: new HandwritingStroke(),
startTime: Date.now(),
};
addPoint(event);
}
Tambahkan titik
Setelah membuat {i>stroke<i}, Anda harus langsung menambahkan titik pertama ke sana. Saat Anda akan
menambahkan lebih banyak
poin lain, maka masuk akal untuk menerapkan logika pembuatan titik dalam metode terpisah. Di kolom
dalam contoh berikut, metode addPoint()
menghitung waktu yang telah berlalu dari stempel waktu referensi.
Informasi temporal bersifat opsional, tetapi dapat meningkatkan kualitas pengenalan. Kemudian, ia membaca X dan
Koordinat Y dari kejadian 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. Poin-poin itu
perlu ditambahkan ke {i>stroke<i} juga. Kejadian ini juga bisa dimunculkan jika pointer tidak dalam
"turun" status, misalnya saat menggerakkan kursor melintasi layar tanpa menekan mouse
tombol. Pengendali peristiwa dari contoh berikut memeriksa apakah ada goresan aktif, dan menambahkan
ke titik baru.
canvas.addEventListener('pointermove', (event) => {
if (activeStroke) {
addPoint(event);
}
});
Mengenali teks
Ketika pengguna mengangkat pointer lagi, Anda bisa menambahkan {i>stroke<i} ke gambar Anda dengan memanggil
Metode addStroke()
. Contoh berikut juga mereset activeStroke
, sehingga pointermove
tidak akan menambahkan titik ke goresan yang telah selesai.
Selanjutnya, saatnya mengenali input pengguna dengan memanggil metode getPrediction()
di
gambar. Pengenalan biasanya memerlukan waktu kurang dari beberapa ratus milidetik, sehingga Anda dapat menjalankan 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 memberikan pilihan kemungkinan kecocokan kepada pengguna, dan meminta mereka memilih
sebelumnya. Atau, Anda dapat langsung memilih prediksi yang paling mungkin, yang akan saya lakukan di
contoh.
Objek prediksi berisi teks yang dikenali dan hasil segmentasi opsional, yang akan saya bahas dalam bagian berikut.
Wawasan 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 kode yang dikenali
karakter yang dapat diidentifikasi pengguna (grapheme
) beserta posisinya di 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 lagi grafem yang dikenali di kanvas.
Pengenalan lengkap
Setelah pengenalan selesai, Anda dapat membebaskan resource dengan memanggil metode clear()
di
HandwritingDrawing
, dan metode finish()
pada HandwritingRecognizer
:
drawing.clear();
recognizer.finish();
Demo
Komponen web <handwriting-textarea>
mengimplementasikan
ditingkatkan secara progresif, kontrol pengeditan yang memungkinkan penulisan tangan
pengenalan objek. Dengan mengklik tombol di sudut kanan bawah
kontrol pengeditan, Anda mengaktifkan
mode menggambar. Setelah Anda selesai menggambar, komponen web akan secara otomatis memulai
pengenalan dan menambahkan teks yang
dikenali kembali ke kontrol pengeditan. Jika Pengenalan Tulis Tangan
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
di luar, termasuk languages
dan recognitiontype
. Anda bisa menetapkan konten kontrol melalui
Atribut value
:
<handwriting-textarea languages="en" recognitiontype="text" value="Hello"></handwriting-textarea>
Untuk mendapatkan informasi tentang perubahan apa pun pada nilai, Anda dapat memproses peristiwa input
.
Anda dapat mencoba komponen ini menggunakan demo ini di Glitch. Pastikan juga untuk melihat kode sumber. Untuk menggunakan kontrol di aplikasi, dapatkan dari npm.
Keamanan dan izin
Tim Chromium merancang dan menerapkan API Pengenalan Tulis Tangan menggunakan prinsip inti didefinisikan dalam Mengontrol Akses ke Fitur Platform Web yang Canggih, termasuk informasi kontrol, transparansi, dan ergonomi.
Kontrol pengguna
Handwriting Recognition API tidak dapat dinonaktifkan oleh pengguna. Konfigurasi ini hanya tersedia untuk situs yang dikirimkan melalui HTTPS, dan hanya boleh dipanggil dari konteks penjelajahan tingkat atas.
Transparansi
Tidak ada indikasi jika pengenalan tulis tangan aktif. Untuk mencegah pelacakan sidik jari, browser menerapkan tindakan penanggulangan, 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.
Beri tahu kami tentang desain API
Apakah ada sesuatu tentang API yang tidak berfungsi seperti yang Anda harapkan? Atau apakah ada metode yang hilang yang dibutuhkan untuk menerapkan ide Anda? Memiliki pertanyaan atau komentar tentang keamanan model? Ajukan masalah spesifikasi di repo GitHub yang sesuai, atau tambahkan pendapat Anda ke masalah yang ada.
Laporkan masalah terkait penerapan
Apakah Anda menemukan bug pada implementasi Chromium? Atau apakah implementasinya berbeda dengan spesifikasi?
Laporkan bug di new.crbug.com. Pastikan untuk menyertakan detail sebanyak mungkin,
instruksi sederhana untuk mereproduksi, dan masukkan Blink>Handwriting
dalam kotak Components.
Glitch sangat cocok untuk membagikan repro dengan cepat dan mudah.
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 mendukung mereka.
Bagikan rencana Anda untuk menggunakannya di thread Discourse WICG. Kirim tweet ke
@ChromiumDev menggunakan hashtag
#HandwritingRecognition
dan beri tahu kami tempat serta
cara Anda menggunakannya.
Tautan Bermanfaat
- Penjelasan
- Draf spesifikasi
- Repositori GitHub
- ChromeStatus
- Bug Chromium
- Peninjauan TAG
- Niat untuk Membuat Prototipe
- Thread WebKit-Dev
- Posisi standar Mozilla
Ucapan terima kasih
Artikel ini diulas oleh Joe Medley, Honglin Yu, dan Jiewei Qian. Banner besar oleh Samir Bouaked di Buka pembuka.