DETEKSI WAJAH DENGAN METODE CONSTRAINT LOCAL MODELS MELALUI PENDEKATAN R DENGAN IMPLEMENTASI PADA WEBGL LAPORAN PROYEK NAMA KELOMPOK AGNAN ZAKARIYA MUHAMMAD RIDWAN ISMANU WILDAN FIRDAUS GUSTI PRIBADI R. S. : 5A412004 : 54411947 : 57411402 : 55409234 Diajukan guna memenuhi tugas kelompok mata kuliah Grafik Komputer II FAKULTAS TEKNIK INDUSTRI JURUSAN TEKNIK INFORMATIKA UNIVERSITAS GUNADARMA DEPOK 2014
124
Embed
Deteksi Wajah Dengan Metode Constraint Local Models
Deteksi wajah atau yang biasa di kenal dengan sebutan face recognition adalah metode komputerisasi yang dirancang untuk mengidentifikasi wajah manusia dari gambar digital atau frame video. Teknologi ini memindai gambar tersebut, dan mencari apakah di sana ditemukan struktur dan kontur wajah manusia yang terdiri dari sepasang mata, satu hidung, satu bibir, serta sepasang pipi dan rahang. Beberapa bentuk persamaan telah di ditawarkan untuk menangani proses artificial pengenalan wajah ini, diantaranya adalah metode persamaan Constraint Local Models (CLM).
Welcome message from author
This document is posted to help you gain knowledge. Please leave a comment to let me know what you think about it! Share it to your friends and learn new things together.
Transcript
DETEKSI WAJAH DENGAN METODE CONSTRAINT
LOCAL MODELS MELALUI PENDEKATAN R DENGAN IMPLEMENTASI PADA WEBGL
LAPORAN PROYEK
NAMA KELOMPOK
AGNAN ZAKARIYA
MUHAMMAD RIDWAN ISMANU
WILDAN FIRDAUS
GUSTI PRIBADI R. S.
: 5A412004
: 54411947
: 57411402
: 55409234
Diajukan guna memenuhi tugas kelompok mata kuliah Grafik Komputer II
FAKULTAS TEKNIK INDUSTRI JURUSAN TEKNIK INFORMATIKA
UNIVERSITAS GUNADARMA DEPOK
2014
2
ABSTRAK
Deteksi wajah atau yang biasa di kenal dengan sebutan face recognition adalah
metode komputerisasi yang dirancang untuk mengidentifikasi wajah manusia dari
gambar digital atau frame video. Teknologi ini memindai gambar tersebut, dan
mencari apakah di sana ditemukan struktur dan kontur wajah manusia yang terdiri
dari sepasang mata, satu hidung, satu bibir, serta sepasang pipi dan rahang. Beberapa
bentuk persamaan telah di ditawarkan untuk menangani proses artificial pengenalan
wajah ini, diantaranya adalah metode persamaan Constraint Local Models (CLM).
CLM merupakan pemodelan matematika dengan dasar pendekatan dari
metode regularized landmark mean-shift, seperti yang telah di jelaskan pada paper
Jason M. Saragih yang berjudul Deformable Model Fitting by Regularized
Landmark Mean-Shift. Metode ini berprinsip pada eksperimen numerik, dengan
melakukan pendekatan yang seksama dalam prosesnya, metode ini terbukti dapat
mengungguli beberapa metode yang ada pada umumnya untuk melakukan
serangkaian tugas memindai wajah secara generik.
3
DAFTAR ISI
COVER ABSTRAK i DAFTAR ISI 3
BAB I PENDAHULUAN 4 1.1 Latar Belakang 4 1.2 Batasan Masalah 5 1.3 Tujuan Penulisan 5 1.4 Metode Penelitian 5 1.5 Sistematika Penulisan 7
BAB II LANDASAN TEORI 8 2.1. Sistem Pengenalan Wajah 8 2.2. Proses Pengenalan Wajah 10 2.3. Pengenalan Bahasa R 11 2.3.1. Dasar Algoritma Matriks pada R 12
2.3.1.1. Fungsi Matriks pada R 14 2.4. Pengenalan WebGL 15 4.1 Implementasi Browser Desktop 17 4.2 Implementasi Browser Mobile 17 2.5. Pengenalan Jquery 18 2.6. CLMTracker Library 18
BAB III PERANCANGAN ALGORITMA DAN PENDEKATAN MODEL 20 3.1. Perancangan Algoritma Dasar 20 3.1.1. Algoritma Matriks 21
3.1.1.1. Deskripsi Algoritma Matriks 22 3.1.1.2. Pendekatan Peudocode pada C++ 23 3.1.1.3. Pendekatan Peudocode pada R 25
3.2. Memulai pendekatan mpdel menggunakan R 26 3.2.1. Membaca Data pada R 27 3.1.2. Algoritma dengan variabel titik kunci pada data citra dengan R 34 3.1.3. Algoritma dengan Benchmark sederhana dengan R 38 3.1.4. Algoritma dengan penggunakan patch gambar dengan R 41 3.1.5. Algoritma eksperimental dengan R 45 3.3. Perancangan penggunaan tapis pada (CLM) 47 3.3.1. Tapis Korelasi MOSSE 47 3.3.2. Transformasi Fourier Cepat 48 3.3.3. Tracker Titik Kunci (Keypoints) 49 3.3.4. Implementasi Eigenvalues dan Eigenvector 50 3.3.5. Implementasi Jacobian Matriks 51
BAB IV IMPLEMENTASI PROGRAM 52 4.1. Implementasi pada WebGl 52 4.1.1. Implementasi Constrain Local Models pada gambar 53 4.1.2. Substitusi Wajah 54 4.1.3. Masking Wajah 55 4.1.4. Deformasi Realtime Wajah 56 4.1.4. Deteksi Emosi Wajah 57
BAB V PENUTUP 5.1. Kesimpulan 59 5.2. Saran 59
DAFTAR PUSTAKA 60 LAMPIRAN 67
4
PENDAHULUAN
1.1 Latar Belakang
Beberapa tahun terakhir perkembangan teknologi berkembang sangat pesat
dari perkembangan tersebut memunculkan beberapa perkembangan yang baik
terhadap teknologi pengenalan wajah manusia yang mendapatkan perhatian serius
dari beberapa peneliti dibidang face localization yaitu pendeteksian wajah manusia
namun dengan asumsi hanya ada satu wajah manusia di dalam citra, penjejakan wajah
(face tracking) untuk memperkirakan lokasi suatu wajah manusia dalam video
secara real time, dan pengenalan ekspresi wajah (facial expression recognition) untuk
mengenali kondisi emosi manusia.
Selain itu dalam bidang penelitian pemrosesan wajah (face processing),
pendeteksi wajah manusia (face detection) adalah salah satu tahap awal yang sangat
penting di dalam proses pengenalan wajah manusia (face recognition). Sistem
pengenalan wajah manusia digunakan untuk membandingkan satu citra wajah
manusia masukan dengan suatu database wajah dan menghasilkan wajah yang paling
cocok dengan citra tersebut. Dengan berkembangnya teknologi yang berkembang
pesat dan beberapa penelitian tentang pengenalan wajah, hal tersebut dapat
diimplementasikan pada pembuatan sistem keamanan suatu perusahaan, dengan
sistem pengenalan wajah manusia seseorang yang tidak memiliki hak akses tidak
dapat masuk ke dalam ruangan tersebut.
Dalam pengenalan wajah terdapat beberapa metode yang biasa digunakan
antara lain Principal Component Analysis, Constrained Local Models dan Edge
detection. Constrained Local Models merupakan sebuah metode dalam mengekstraksi
ciri suatu objek. Dalam mengekstraksi ciri, CLM membagi beberapa kelas dalam
5
pencarian ciri, misalnya ada data enam orang, dimana setiap orang terbagi menjadi
setiap kelas. Jika dibandingkan dengan metode-metode lain, CLM memiliki ketepatan
yang sangat tinggi dalam mengenali wajah seseorang, dikarenakan dalam metode
CLM ini memiliki banyak data dalam pengenalan wajah seseorang.
1.2 Batasan Masalah
Untuk menjaga fokus dari penulisan ini, maka beberapa batasan yang
diberikan sebagai berikut :
1. Wajah yang akan dideteksi adalah wajah yang menghadap ke depan, dalam
posisi tegak dan tidak terhalangi sebagian objek lain
2. Metode yang dipakai adalah metode Constrained Local Models dan Edge
detection.
3. Citra yang dideteksi menggunakan format BMP atau JPG
4. Hasil deteksi wajah merupakan titik lokasi penandaan batas wajah.
1.3 Tujuan Penulisan
Tujuan dari penulisan ini adalah untuk membuat pendekatan dalam memahami
bagaimana deteksi wajah bekerja menggunakan metode Constraint Local Models
(CLM). Dengan pendekatan ini kita akan belajar lebih dalam bagaimana sebuah
sistem dapat membangun sistem jaringan syarat tiruan atau Artificial Inteligent dalam
mendeteksi wajah manusia.
1.4 Metode Penelitian
Metode penelitian yang diterapkan pada penulisan laporan ini adalah
memperbaharui hasil penulisan yang telah ada untuk lebih mengembangkannya.
6
Selain itu dilengkapi juga dengan literasi dari berbagai referensi diantaranya melalui
jurnal, dokumentasi, dan log yang terdapat pada sumber kode terbuka versi paling
terbaru melalui SVN Github.
IDE dan Perangkat lunak pendukung lainnya yang di gunakan sebagai penunjang
penulisan ini diantaranya:
- Textwrangler
- Browser Mozilla Firefox
Berikut dengan library yang mendukungnya, antara lain:
- JQuery
- CLMTracker
Hardware yang digunakan:
- Intel dual core 2,0 GHz
- RAM 2 Gb
- VGA approx memory shared 256 Mb
- Webcam 1,3 MP
Dalam pembuatan Penulisan ini kami melakukan beberapa tahapan yaitu:
- Merancang rangkaian hirarki teknis Penulisan.
- Tahap berikutnya adalah analisis library dan instalasi toolkit pada IDE.
- Pada tahap akhir yaitu melakukan uji coba, dimana kami menguji aplikasi ini
menggunakan webcam.
7
1.5 Sistematika Penulisan
Penulisan ilmiah ini terdiri dari 4 BAB disertai lampiran dan mempunyai garis besar
sebagai berikut:
BAB I PENDAHULUAN, Bab ini terdiri dari latar belakang masalah, batasan
masalah, tujuan penulisan, metode penelitian dan sistematika penulisan.
BAB II LANDASAN TEORI, Bab ini membahas teori pengenalan wajah,
penggunaan bahasa R, penggunaan WebGL dan library pendukung.
BAB III PERANCANGAN ALGORITMA, Bab ini menerangkan gambaran umum
aplikasi dan perancangan algoritma.
BAB IV IMPLEMENTASI PROGRAM, Bab ini menerangkan pembuatan,
pengimplementasian program dan spesifikasinya.
BAB V PENUTUP, Bab ini berisi kesimpulan dan saran.
8
BAB II
LANDASAN TEORI
1. Sistem Pengenalan Wajah
Pengenalan wajah manusia adalah bidang penelitian penting dengan banyak
aplikasi yang dapat menggunakannya. Penelitian terhadap pengenalan wajah manusia
sudah banyak dilakukan dengan kelebihan dan kekurangan tertentu. Hal ini
disebabkan karena wajah manusia merepresentasikan sesuatu yang kompleks dan
mengembangkan model komputasi untuk pengenalan wajah manusia adalah hal yang
sulit.
Pengenalan wajah ini dibagi menjadi dua bagian yaitu: dikenali dan tidak
dikenali, setelah dilakukan perbandingan dengan pola yang sebelumnya disimpan di
dalam database. Perhitungan model pengenalan wajah memiliki beberapa masalah.
Kesulitan muncul ketika wajah dipresentasikan dalam suatu pola yang berisi
informasi unik yang membedakan dengan wajah lain. Metode pengenalan wajah
memiliki dua prosedur, yaitu :
a) Pengenalan kontur wajah dengan mengenali bentuk hidung, mata dan mulut dan
bentuk korelasi diantara keduanya. Karakteristik organ tersebut kemudian
dinyatakan dalam bentuk vektor.
b) Analisis komponen yang prinsipil, berdasarkan informasi dari konsep ini, mencari
perhitungan model terbaik yang menjelaskan bentuk wajah dengan mengutip
informasi yang paling relevan yang terkandung didalam wajah tersebut.
9
Dibalik kemudahan pengenalan wajah, ada beberapa masalah yang mungkin timbul
dalam proses pengenalan wajah yang biasa disebut dengan robust, yaitu:
a) Perubahan skala Citra seseorang dapat dipresentasikan berbeda diakibatkan
perbedaan jarak antara wajah dengan kamera. Semakin dekat jarak maka citra
akan semakin besar.
b) Perubahan posisi Citra seseorang dapat dipresentasikan berbeda diakibatkan
perubahan posisi seseorang ataupun perubahan sudut pengambilan wajah.
c) Perubahan cahaya Citra seseorang dapat dipresentasikan berbeda diakibatkan
perubahan intensitas cahaya yang terjadi pada saat pengambilan citra.
Perubahan detail dan ekspresi Citra seseorang dapat dipresentasikan berbeda
diakibatkan perubahan detail seperti adanya janggut, kumis, pemakaian aksesoris,
perubahan gaya, perubahan ekspresi wajah menjadi tertawa, tersenyum, muram,
menangis dan lain sebagainya yang dapat mengakibatkan perubahan citra.
Langkah-langkah dalam proses pembuatan sistem pengenalan wajah berbeda
satu dengan yang lain. Hal ini disebabkan karena adanya faktor-faktor seperti ukuran
database atau training set dari citra wajah, jenis input yang digunakan (citra foto
atau video), derau (noise) pada citra dan lain-lain.
10
2. Proses Pengenalan Wajah
Pada dasarnya proses dalam pengenalan wajah terbagi menjadi beberapa bagian
seperti pada blok diagram dibawah ini:
Gambar 1.2.1. Diagram Blok Pengenalan Wajah
Setiap bagian dalam diagram di atas dapat dilakukan melalui metode yang berbeda-
beda. Sebagai contoh, untuk mendeteksi wajah, kita dapat menggunakan metode
berbasis fitur (feature-based methods) untuk mendeteksi fitur pada wajah (mata,
hidung, mulut), atau dapat juga menggunakan deteksi warna kulit.
Metode Pendekatan Deteksi Wajah
Banyak sekali metode pendekatan yang dapat dilakukan pada tahap deteksi wajah
pada kondisi yang berbeda-beda. Metode pendekatan ini adalah metode berbasis fitur
(feature-based methods), template matching, metode berbasis tampilan (appearance-
based methods). Feature-based methods bertujuan untuk mendeteksi keberadaan dan
lokasi fitur seperti mata, hidung, bibir, alis, dan lain-lain. Metode template
matching adalah sebuah metode dengan menggunakan template yang disimpan untuk
mendeskripsikan sebuah wajah secara utuh atau fitur wajah secara terpisah. Dalam
metode template matching ini, keberadaan sebuah wajah dapat diketahui melalui
perhitungan nilai korelasi antara citra masukan dan template yang disimpan.
11
Metode appearance-based adalah metode yang menggunakan “template” yang
dihasilkan dari training pada dataset citra dan digunakan untuk mendapatkan variabel
yang mewakili keberadaan dari wajah itu sendiri. Dibandingan feature-
based dan template matching, metode appearance-based memberikan hasil yang
lebih baik ketika diterapkan pada sistem dengan sejumlah besar sampel.
Berikut adalah pengkategorian dari deteksi wajah.
Gambar 1.2.2. Pengkategorian Deteksi Wajah
3. Pengenalan Bahasa R
R adalah bahasa pemrograman dan perangkat lunak untuk analisis statistika
dan grafik. R dibuat oleh Ross Ihaka dan Robert Gentleman di Universitas Auckland,
Selandia Baru, dan kini dikembangkan oleh R Development Core Team, dimana
Chambers merupakan anggotanya. R dinamakan sebagian setelah nama dua
pembuatnya (Robert Gentleman dan Ross Ihaka), dan sebagian sebagian dari nama S.
Bahasa R kini menjadi standar de facto di antara statistikawan untuk pengembangan
perangkat lunak statistika, serta digunakan secara luas untuk pengembangan
perangkat lunak statistika dan analisis data.
12
R merupakan bagian dari proyek GNU. Kode sumbernya tersedia secara bebas
di bawah Lisensi Publik Umum GNU, dan versi biner prekompilasinya tersedia untuk
berbagai sistem operasi. R menggunakan antarmuka baris perintah, meski beberapa
antarmuka pengguna grafik juga tersedia.
R menyediakan berbagai teknik statistika (permodelan linier dan nonlinier, uji
statistik klasik, analisis deret waktu, klasifikasi, klasterisasi, dan sebagainya) serta
grafik. R, sebagaimana S, dirancang sebagai bahasa komputer sebenarnya, dan
mengizinkan penggunanya untuk menambah fungsi tambahan dengan mendefinisikan
fungsi baru. Kekuatan besar dari R yang lain adalah fasilitas grafiknya, yang
menghasilkan grafik dengan kualitas publikasi yang dapat memuat simbol
matematika. R memiliki format dokumentasi seperti LaTeX, yang digunakan untuk
menyediakan dokumentasi yang lengkap, baik secara daring (dalam berbagai format)
maupun secara cetakan.
3.1. Dasar Algoritma Matriks pada R
Misalkan A, B dua matriks persegi pada ring R. Kita ingin menghitung produk
matriks C sebagai
Jika matriks A, B bukan bertipe 2n x 2n kita isi baris-baris dan kolom-kolom yang
kosong dengan nol.
Kita partisi A, B dan C kedalam matriks blok yang berukuran sama.
dengan
lalu
13
Dengan konstruksi ini kita tidak mengurangi jumlah dari perkalian-perkalian. Kita
masih memerlukan 8 perkalian-perkalian untuk menghitung matriks-matriks Ci,j ,
dengan jumlah perkalian yang sama kita perlukan ketika menggunakan matriks
perkalian standar.
Sekarang sampai pada bagian terpenting. Kita tetapkan matriks baru
Yang kemudian digunakan untuk mengekspresikan Ci,j dalam bentuk Mk. Karena kita
telah mendefenisikan Mk kita bisa mengeliminasi satu perkalian matriks dan
mengurangi jumlah perkalian-perkalian menjadi 7 (satu perkalian matriks untuk
tiap Mk) dan ekspresi Ci,j sebagai
Kita iterasikan bagian diatas ke-n kali proses sampai submatriks-submatriks menjadi
angka-angka.
14
3.1.1. Fungsi Matriks menggunakan Bahasa R
Matriks A adalah kumpulan elemen data yang diatur dalam tata letak persegi
panjang dua dimensi. Berikut ini adalah contoh dari sebuah matriks dengan 2 baris
dan 3 kolom. Pada bahasa R, perhitungan matriks mengimplementasi Algoritma
Strassen. Dalam matematika, khususnya aljabar linear Algoritma Strassen
merupakan sebuah algoritma yang dinamakan oleh Volker Strassen yang merupakan
sebuah algoritma yang digunakan untuk perkalian matriks yang secara asimtot lebih
cepat dari pada algoritma perkalian matriks standar dan sangat berguna dalam
penggunaanya untuk matriks yang berukuran besar.
Kami mereproduksi representasi memori dari matriks menggunakan fungsi dalam
bahasa pemrograman R. Dengan unsur-unsur data dari jenis dasar yang sama.
> A = matrix (
+ C (2, 4, 3, 1, 5, 7), # elemen data
+ Nrow = 2, # jumlah baris
+ Ncol = 3, # jumlah kolom
+ Byrow = TRUE) # mengisi matriks dengan baris
> A # mencetak matriks
[1] [2] [3]
[1,] 2 4 3
[2,] 1 5 7
Sebuah elemen pada baris-m dan kolom-n dari matriks A dapat diakses oleh ekspresi
A [m, n]. > A [2, 3] # elemen pada baris 2, kolom 3
[1] 7
Seluruh baris-m pada matriks A dapat diekstraksi oleh ekspresi A[m,]. > A [2,] # baris 2
15
[1] 1 5 7
Demikian pula, seluruh kolom-n pada matriks A dapat diekstraksi oleh ekspresi A[,
n]. > A [3] # 3 kolom
[1] 3 7
Kami juga dapat mengekstrak lebih dari satu baris atau kolom dalam satu waktu. > A [, c (1,3)] # 1 dan kolom ke-3
[1] [2]
[1,] 2 3
[2,] 1 7
Jika kita menetapkan nama untuk baris dan kolom dari matriks tersebut, kita dapat
menentukannya dengan mengakses elemen menggunakan nama yang ditetapkan. > Dimnames (A) = list(
+ c ("row1", "row2"), # nama baris
+ C ("col1", "col2", "col3")) # nama kolom
> A # print A
col1 col2 col3
row1 2 4 3
row2 1 5 7
> A ["row2", "col3"] # elemen pada baris 2, kolom 3
[1] 7
4. Pengenalan WebGL
WebGL (Web Graphics Library) adalah JavaScript API untuk rendering grafis
3D interaktif dan grafis 2D dalam browser web yang kompatibel tanpa menggunakan
plug-in. WebGL terintegrasi sepenuhnya ke semua standar web browser yang
memungkinkan penggunaan percepatan GPU fisika dan pengolahan gambar dan efek
sebagai bagian dari kanvas halaman web. Elemen WebGL dapat dicampur dengan
elemen HTML lainnya dan composited dengan bagian-bagian lain dari latar belakang
16
halaman atau halaman. WebGL program terdiri dari kode kontrol ditulis
dalamJavaScript dan kode shader yang dijalankan pada komputer Graphics
Processing Unit (GPU). WebGL dirancang dan dipelihara oleh Kelompok Khronos
non-profit.
WebGL didasarkan pada OpenGL ES 2.0 dan menyediakan sebuah API untuk
grafis 3D. Untuk alasan keamanan, GL_ARB_robustness (OpenGL 3.x) atau
GL_EXT_robustness (OpenGL ES) diperlukan. Ia menggunakan elemen kanvas
HTML5 dan diakses menggunakan antarmuka Document Object Model. Manajemen
memori otomatis disediakan sebagai bagian dari bahasa JavaScript.
WebGL tumbuh dari eksperimen Canvas 3D dimulai oleh Vladimir
Vukićević di Mozilla. Vukićević pertama menunjukkan prototipe 3D kanvas pada
tahun 2006. Pada akhir tahun 2007, baik Mozilla dan Opera telah membuat
implementasi sendiri terpisah. Pada awal 2009, non-profit teknologi konsorsium Grup
Khronos memulai Kelompok Kerja WebGL, dengan partisipasi awal
dari Apple, Google, Mozilla, Opera, dan lain-lain. Versi 1.0 dari spesifikasi WebGL
dirilis Maret 2011. Pada Maret 2012, ketua kelompok kerja adalah Ken Russell.
Aplikasi awal Terkemuka dari WebGL termasuk Google Maps dan Zygote Body.
17
4.1 Implementasi Browser Desktop
a) Memiliki kartu grafis yang mampu dengan driver diperbarui sejak versi 4.0.
Mozilla Firefox 8.0 dan versi yang lebih baru menggunakan Cross-asal
berbagi sumber daya (CORS) untuk mengontrol semua lintas domain tekstur
WebGL.
b) Google Chrome - WebGL telah diaktifkan pada semua platform yang
memiliki kartu grafis yang mampu dengan driver diperbarui sejak versi 9.
Google Chrome 13.0 dan versi yang lebih baru menggunakan Cross-asal
berbagi sumber daya (CORS) untuk mengontrol semua lintas domain tekstur
WebGL.
c) Safari - Safari 5.1 dan versi yang lebih baru diinstal pada Mac OS X Lion dan
Mac OS X Snow Leopard dukungan diterapkan untuk WebGL, yang
dinonaktifkan secara default.
d) Opera - WebGL telah diimplementasikan di Opera 11, dan 12 juga
dinonaktifkan secara default.
e) Internet Explorer - Saat ini, Microsoft tidak berencana untuk mendukung
WebGL karena alasan keamanan dan karena itu tidak menjadi standar W3C
belum, walaupun dukungan WebGL dapat secara manual ditambahkan ke
Internet Explorer menggunakan plugin pihak ketiga seperti Chrome Frame dan
IEWebGL.
4.2 Implementasi Browser Mobile
a) BlackBerry PlayBook - WebGL tersedia melalui WebWorks dan browser di
PlayBook OS 2.0
18
b) Firefox untuk mobile (en) - WebGL tersedia untuk perangkat Android dalam
membangun tidak stabil sejak awal 2011.
c) Sony Ericsson Xperia berbagai smartphone Android memiliki kemampuan
WebGL setelah upgrade firmware.
d) Opera Mobile (en) 12 akhir mendukung WebGL (pada Android saja).
e) Tizen 1.0
5. Pengenalan JQuery
jQuery adalah pustaka JavaScript kecil bersumber terbuka yang menekankan
pada interaksi antara JavaScript dan HTML. Pustaka ini dirilis pada Januari 2006 di
BarCamp NYC oleh John Resig dan berlisensi ganda di bawah MIT dan GPL.
Microsoft dan Nokia telah mengumumkan akan mengemas jQuery di platform
mereka. Microsoft awalnya mengadopsinya dalam Visual Studio untuk digunakan
dalam ASP.NET AJAX dan ASP.NET MVC Framework, sedangkan Nokia akan
mengintegrasikannya dalam kerangka Web Run-Time mereka.
6. CLMTracker Library
Clmtrackr adalah sebuah library javascript yang digunakan untuk mengenali
pemindaian model wajah pada sebuah citra atau video. Library ini merupakan
pemodelan matematika dari Constrained Local Models dengan dasar pendekatan dari
metode regularized landmark mean-shift, seperti yang telah di jelaskan pada paper
Jason M. Saragih yang berjudul Deformable Model Fitting by Regularized
Landmark Mean-Shift. Model pas terdeformasi secara aktif telah dikenal dalam
komunitas komputer vision selama lebih dari satu dekade. Akibatnya, banyak
19
pendekatan telah diusulkan dengan berbagai tingkat keberhasilan. Sebuah kelas
pendekatan yang menjanjikan secara substansial adalah salah satu yang membuat
prediksi independen mengenai lokasi dari landmark model, yang dikombinasikan
dengan persamaan atas gerak sendi mereka. Sebuah tema umum dalam inovasi untuk
pendekatan ini adalah penggantian distribusi lokasi tengara kemungkinan, yang
diperoleh dari masing-masing detektor lokal, dengan bentuk parametrik sederhana.
Dalam karya ini, strategi optimasi berprinsip diusulkan di mana representasi
nonparametrik dari likelihoods ini dimaksimalkan dalam hirarki estimasi untuk
merapihkan.
Sehingga menghasilkan persamaan yang baru untuk menyimpan rata-shift
selama landmark, dengan regularisasi yang dipaksakan melalui persamaan global
selama pergerakannya. Ekstensi untuk menangani oklusi parsial dan mengurangi
kompleksitas komputasi juga disajikan. Melalui eksperimen numerik, pendekatan ini
terbukti dapat mengungguli beberapa metode yang ada pada umumnya untuk
melakukan tugas memindai wajah secara generik.
20
BAB III
PERANCANGAN ALGORITMA DAN PENDEKATAN MODEL
3.1. Perancangan Algoritma Dasar
Dalam asas rasionalis natura mengungkapkan bahwa semesta ini adalah suatu
substansi tunggal yang mempunyai pola. Sebagian dari pernyataan tersebut dapat di
terima dan sebagian lagi tidak, tapi kunci pemahamannya dari aspek pemikiran
tersebut adalah pernyataan bahwa semua yang terjadi di dunia ini mempunyai pola.
Benar, bagaimana kita melihat aturan alam tentang siang dan malam, bagaimana kita
melihat tentang aturan bentuk manusia dengan rasio emasnya, lalu jarak orbit,
peredaran matahari, susunan tata surya beserta galaksi dsb. Semua mempunyai pola
yang beraturan tentunya.
Pada Matriks, yang hampir kita kenal dari pelajaran Sekolah Menengah
Pertama sampai tingkat pendidikan yang lebih lanjut. Jika Anda pernah bertanya-
tanya apa sebenarnya fungsi dari pembelajaran tersebut, lalu apakah pembelajaran ini
bermanfaat untuk kehidupan nyata (dalam arti, dapat di implementasi tidak hanya
sekedar teori) tentunya jika Anda tidak ingin mengetahuinya lebih lanjut, tanpa
menyadarinya semua hal tersebut telah nampak nyata dan dekat dengan keseharian
kita. Pada era digital ini, mungkin anda tidak menyadari bahwa foto-foto digital Anda
mengandung implementasi pola Matriks.
Salah satu proses yang penting dalam pengenalan objek yang tersaji secara
visual (berbentuk gambar) adalah segmentasi. Segmentasi objek di dalam citra
bertujuan memisahkan wilayah (region) objek dengan wilayah latar belakang.
21
Selanjutnya, wilayah objek yang telah tersegmentasi digunakan untuk proses
berikutnya (deteksi tepi, pengenalan pola, dan interpretasi objek). Metode segmentasi
yang umum adalah pengambangan citra (image thresholding). Operasi
pengambangan mensegmentasikan citra menjadi dua wilayah, yaitu wilayah objek
dan wilayah latar belakang. Wilayah objek diset berwarna putih sedangkan sisanya
diset berwarna hitam (atau sebaliknya). Hasil dari operasi pengambangan adalah citra
biner yang hanya mempunyai dua derajat keabuan: hitam dan putih. Sebelum proses
segmentasi, citra mengalami beberapa pemrosesan awal (preprocessing) untuk
memperoleh hasil segmentasi objek yang baik. Pemrosesan awal adalah operasi
pengolahan citra untuk meningkatkan kualitas citra (image enhancement).
3.1.1 Algoritma Matriks
Berikut adalah algoritma dari matriks yang telah terenkapsulasi sebagai fungsi
di R. Dalam artian, pada bahasa R fungsi matriks hanya tinggal di gunakan saja tanpa
harus di inisiasi kembali. Untuk itu kami akan menerangkan lebih jauh tentang
algoritma pada matriks tersebut dengan beberapa pendekatan tentunya.
Judul: Algoritma fungsi matriks berordo-N pada operasi dasar aritmatika antar
matriks
Input : Data bilangan integer dalam bentuk array
Output : Hasil operasi dasar aritmatika pada matriks berordo-N
Proses :
Inisiasi variabel
m, n, row, col, matrix_one[n][m], matrix_two[n][m], matrix_res[n][m] ⇐ (semua)
bilangan integer
Deklarasi proses
22
perulangan 1 : untuk m ⇐ 0 ke row kerjakan, inkremental
perulangan 2 : untuk n ⇐ 0 ke col kerjakan k, inkremental
Judul: Algoritma fungsi matriks berordo-N pada operasi dasar aritmatika antar
matriks
Input : Data bilangan integer dalam bentuk array
Output : Hasil operasi aritmatika pada matriks berordo-N
Proses :
a) Inisiasi variabel
Blok ini menjelaskan inisiasi awal pada tiap variabel yang terdapat pada
fungsi matriks.
Dimana: m, n, row, col, matrix_one[n][m], matrix_two[n][m],
matrix_res[n][m] ⇐ (semua) bilangan integer.
b) Deklarasi proses
Blok ini menjelaskan inisiasi awal pada tiap variabel yang terdapat pada
fungsi matriks.
Dimana:
Pada perulangan 1: untuk m bernilai 0 dikomparasi dengan nilai “row”
maka statement dibawahnya akan di kerjakan, dan terjadi inkremental pada m.
23
Sedangkan pada perulangan 2: untuk n bernilai 0 dikomparasi dengan nilai
“col” maka statement dibawahnya akan di kerjakan, dan terjadi incremental
pada n.
Lalu:
Mencetak hasil dari dari setiap operasi dasar aritmatika yang dilakukan pada
matrix_one dan matrix_two dimana hasilnya akan di simpan pada variabel
matrix_res(ult)
akhiri perulangan 2
akhiri perulangan 1
c) Keterangan
OPS.AR = Operasi Aritmatika
row adalah variabel inputan untuk baris
col adalah variable inputan untuk kolom
3.1.1.2 Pendekatan Pseudocode pada C++
Sebelum menerangkan pseudocode pada bahasa R, kami melakukan
pendekatan pada bahasa C++ sebagai bentuk komparasi pseudocode. Alasan kami
mengkomparasi yaitu untuk memaparkan konsep algoritma pada pseudocode dalam
bentuk bahasa pemrograman yang lebih umum dan lazim di gunakan agar lebih
mudah menjelaskannya secara garis besar. Karena bahasa C++ merupakan bahasa
yang lazim digunakan oleh setiap programmer, maka kami melakukan konversi
bahasa R terhadap C++.
Input: row, col ⇐ user input for (m=0 ; m < row ; m++) { for (n=0 ; n < col ; n++) { matrix_definition[n][m] ⇐ user input
24
} } proses: for (m=0 ; m < row ; m++) { for (n=0 ; n < col ; n++) { matrix_res[n][m] ⇐ matrix_one[n][m](OPS.AR)matrix_two[n][m] } } output: for (m=0 ; m < row ; m++) { for (n=0 ; n < col ; n++) { output ⇐ matrix_res[n][m] } }
Terdapat 3 blok pseudocode, yaitu blok input, blok proses, dan blok output. Berikut
penjelasannya per tiap blok.
Blok input merupakan blok masukan data yang di kehendaki oleh pengguna, dimana
row dan col mewakili inisiasi dari masukan jumlah baris dan kolom. Lalu nilai-m
sama dengan 0 akan dikomparasi dengan nilai row, dimana m mengalami inkremental
dan mendefinisikan pengulangan pada nilai-n sama dengan 0 yang akan di komparasi
dengan nilai col, dimana n akan mengalami inkremental lalu mendefinisikan tiap
inputan pada matrix [n] [m] sesuai data yang di kehendaki.
Blok proses merupakan blok pemrosesan data yang telah di inputkan, dimana row
dan col mewakili inisiasi dari masukan jumlah baris dan kolom. Lalu nilai-m sama
dengan 0 akan dikomparasi dengan nilai row, dimana m mengalami inkremental dan
mendefinisikan pengulangan pada nilai-n sama dengan 0 yang akan di komparasi
dengan nilai col, dimana n akan mengalami inkremental lalu mendefinisikan hasil
operasi aritmatika antara matrix_one dan matrix_two yang disimpan di matrix_res.
Blok output merupakan blok keluaran data yang telah di proses sebelumnya, dimana
row dan col mewakili inisiasi dari masukan jumlah baris dan kolom. Lalu nilai-m
sama dengan 0 akan dikomparasi dengan nilai row, dimana m mengalami inkremental
25
dan mendefinisikan pengulangan pada nilai-n sama dengan 0 yang akan di komparasi
dengan nilai col, dimana n akan mengalami inkremental lalu mendefinisikan hasil
output dari matrix_res.
3.1.1.3 Pendekatan Pseudocode pada R
Berikut adalah pendekatan pseudocode pada R setelah mengkalibrasi pseudocode
pada C++ . Pseudocode pada R lebih sederhana, karena tidak mengalami pengulangan
pada tiap blok. Rekursif hanya terjadi pada blok input.
Input: row, col ⇐ user input for (m=0 ; m < row ; m++) { for (n=0 ; n < col ; n++) { matrix_definition[n][m] ⇐ user input } } proses: matrix_res[n][m] ⇐ matrix_one[n][m](OPS.AR)matrix_two[n][m] } output: output ⇐ matrix_res[n][m] }
Blok input merupakan blok masukan data yang di kehendaki oleh pengguna, dimana
row dan col mewakili inisiasi dari masukan jumlah baris dan kolom. Lalu nilai-m
sama dengan 0 akan dikomparasi dengan nilai row, dimana m mengalami inkremental
dan mendefinisikan pengulangan pada nilai-n sama dengan 0 yang akan di komparasi
dengan nilai col, dimana n akan mengalami inkremental lalu mendefinisikan tiap
inputan pada matrix [n] [m] sesuai data yang di kehendaki.
Blok proses merupakan blok pemrosesan data yang telah di inputkan, mendefinisikan
hasil operasi aritmatika antara matrix_one dan matrix_two yang disimpan di
matrix_res.
26
Blok output merupakan blok keluaran data yang telah di proses sebelumnya,
mendefinisikan hasil output dari matrix_res.
3.2. Memulai pendekatan model menggunakan R
Pada uraian ini kami akan menjelaskan pendekatan melalui data perbandingan
pada sample citra, yang semuanya di lakukan dengan menggunakan bahasa R. Bahasa
R merupakan sebuah open source yang bebas di gunakan siapapun, dikenal luas
sebagai sebuah bahasa yang digunakan untuk perhitungan statistik data.
Penggunaannya hampir dapat di lakukan dari berbagai platform baik itu Windows,
OS X, Linux dan yang lainnya.
Tujuan dari pendekatan ini adalah untuk menunjukan titik kunci kordinat
secara spesifik pada sebuah citra wajah. Sehingga dapat melakukan deteksi wajah
pada sebuah citra. Dari data yang didapat tersebut, kita dapat menentukan bagaimana
sebuah algoritma akan di terapkan pada sebuah Library. Sebelum melakukan
pemodelan ini, kita harus menyiapkan data dan mengunduh file yang di butuhkan
melalui kaggle.com. Kaggle menyediakan file training.zip dan test.zip yang yang
didalamnya ada 7049 contoh citra wajah yang telah di lengkapi dengan lokasi titik
korespondensi. Kami akan menggunakan data tersebut untuk menentukan pendekatan
pada algoritma yang di butuhkan.
File unduhan teresebut mempunyai titik kunci yang dapat diprediksi dan
nilainya ditentukan oleh x, y dengan tipe data real dalam ruang indeks piksel. Ada 15
titik kunci, yang mewakili unsur-unsur wajah, berikut diantaranya:
Pada BAB terakhir ini diuraikan mengenai kesimpulan yang dapat ditarik dari
pengerjaan penulisan ini. Selain itu juga diuraikan mengenai saran-saran yang dapat
diperhatikan untuk pengembangan selanjutnya.
5.1. Kesimpulan
Kesimpulan yang diperoleh berdasarkan ujicoba dan analisa hasil yang telah
dilakukan adalah sebagai berikut :
1. Deteksi wajah dapat dilakukan dengan menggunakan metode Constraint Local
Models, dimana akurasi didapatkan sebesar 86%.
2. Skala citra wajah bisa mempengaruhi hasil dari deteksi wajah.
3. Deteksi fitur wajah dengan histogram proyeksi mampu mencapai akurasi 77%,
namun metode ini tidak mampu mengatasi masalah intensitas cahaya.
5.2. Saran
Beberapa saran yang hendak disampaikan terkait dengan pengerjaan tugas
akhir ini adalah sebagai berikut:
1. Dikembangkan suatu metode paling optimal untuk ekstraksi fitur Wajah.
2. Diperlukan algoritma untuk dapat mendeteksi posisi fitur wajah dengan
kemiringan hampir 90 derajat.
60
(halaman ini dibiarkan kosong)
61
DAFTAR PUSTAKA
[1] Bahlmann, C., Bernard Haasdonk, and Hans Burkhardt., 2002. “Online hand writing recognition using support vector machines – a kernel approch”. Niagara-on-the-Lake, In Int. Workshop on Frontiers in Hadwriting Recognition.
[2] Bennett, K.P., D.H. WU, and L. Auslender., 1998. On Support Vector Decission Trees for Database Marketing. New York. Technical report, Rensselaer Polytechnic Institute.
[4] Brown, M., Grundy, W., Lin, D., Christianini, N., Sugnet, C. , Jr, M., and Haussler, D., 1999. “Support vector machines classification of microarry gene expression data”. Technical support UCSC – CRL 99-09, University California Santa Cruz, Departemen of Computer Science, California, USA.
[6] Drucker, H., Wu, D., andVapnik, V.N., 1999. “Support vector machines for spam categorization”. IEEE Transaction on Neural Network, 10(5):1048-1054.
[7] Dumais, A., Plat, J., Heckerman, D., and Sahami, M., 1998. “Inductive learning algoritms and representation for text categorization”. CIKM-98, 7th ACM International Conference on Information and Knowledge Management, 148-155.
[8] Guyon, I., Boser, B.E., and Vapnik, V.N., 1992. “A training algorithm for optimal margin classifiers”. In the annual workshop of computational learning theory, pages 144–152. ACM.
[9] A. W. Tucker H. W. Kuhn., 1951. “Non-linear programming”. In 2nd on Mathmatical Statistics and
62
Probability, 481–492, Berkley, University of California Press.
[10] T. Jaakkola, M. Diekhans, and Haussler, D., 1998 “A discriminative framework for detecting remote protein homologies”.
[11] Joachims, Thorsten., 1998. “Text categorization with support vector machines: learning with many relevant features”. In Celine Rouveirol Claire Nedellec, editor, (ECML)-98, 10th European Conference on Machine Learning, number 13 in 98, 137–142, Chemnitz, DE, 1998. Springer Verlag, Heidelberg, DE.
[12] Joachims, Thorsten., 1999. “Transductive inference for text classification using support vector machines”. In Saso Dzeroski Ivan Bratko, editor, Proceedings of ICML-99, 16th International Conference on Machine Learning, pages 200–209, Bled, SL. Morgan Kaufmann Publishers, San Francisco,US.
[13] Kim, H. and Park, H., 2003. “Prediction of protein relative solvent accessibility with support vector machines and long-range interaction 3d local descriptor.
[14] Kim, H. and Park, H., 2003. “Protein secondary structure prediction by support vector machines and position-specific scoring matrices”.
[15] Lee, Yuh-Jye and Mangasarian, O. L., 2000. “Ssvm: Smooth support vector machine for classification”. Computational Optimization and Applications, 20(1):5–22.
[16] Lee, Yuh-Jye, Mangasarian, O. L., and Wolberg, W. H., 2000. “Breast cancer survival and chemotherapy: A support vector machine analysis”. DIMACS Series in Discrete Mathematics and Theoretical Computer Science, 55:1–10.
[17] Lee, Yuh-Jye, Mangasarian, O. L., and Wolberg, W. H., 2001. “Survival-time classification of breast cancer patients”. In Data Mining Institute Technical Report 01-03.
[18] Lyu, S., and Farid, H., 2002. “Detecting hidden messages using higher-order statistics and support vector machines”.
63
In 5th International Workshop on Information Hiding, Noordwijkerhout, The Netherlands.
[19] Mangasarian, Olvi L., Street, W. Nick, and Wolberg, William H., 1994. “Breast cancer diagnosis and prognosis via linear programming”. Technical Report MP-TR-1994-10, MP-TR.
[20] Mller, K.R., Smola, A., Rtsch, G., Schlkopf, B., Kohlmorgen, J., and Vapnik, V., 1997. “Predicting time series with support vector machines”. In M. Hasler W. Gerstner, A. Germond and J.D. Nicoud, editors, Articial Neural Networks - ICANN’97, pages 999–1004. Springer Lecture Notes in Computer Science.
[21] Mller, K.R., Smola, A., Rtsch, G., Schlkopf, B., Kohlmorgen, J., and Vapnik, V., 1999. “Using support vector machines for time series prediction”. In B. Schlkopf, C.J.C. Burges, and A.J. Smola, editors, Advances in Kernel Methods, pages 242–253. MIT Press.
[22] Mohan, Anuj., 1999. “Object detection in images by components”.
[23] Rychetsky, M., Ortmann, S., and Glesner, M., 1999. “Construction of a support vector machine with local experts. In Workshop on Support Vector Machines at the International Joint Conference on Artificial Intelligence (IJCAI 99), Stockholm, Sweden.
[24] Rychetsky, M., Ortmann, S., and Glesner, M., 1999. “Support vector approaches for engine knock detection”. In International Joint Conference on Neural Networks (IJCNN 99), Washington, USA.
[25] Mukherjee, Sayan, Osuna, Edgar, and Girosi, Frederico., 1997. Nonlinear prediction of chaotic time series using support vector machines. In IEEE NNSP 97, Amelia Island, Florida, USA.
[26] Mukkamala, Srinivas and Sung, Andrew H., 2003. “A comparative study of techniques for intrusion detection”. In 15th IEEE International Conference on Tools with
64
Artificial Intelligence (ICTAI’03), Sacramento, California, USA.
[27] Cristianini, John Shawe-Taylor Nello., 2000. “An Intoduction to Support Vector Machines and other kernal-based learning methods”. Cambridge University Press.
[28] Osuna, E., Freund, R., and Girosi, F., 1997. “Training support vector machines:an application to face detection”. In CVPR’97, Puerto Rico.
[29] Pal, Mahesh and Mather, Paul M., 2003. “Support vector classifiers for land cover classification”. In Map India 2003 Image Processing and Interpretation.
[30] Papageorgiou, C., Evgeniou, T., and Poggio, T., 1998. “A trainable pedestrian detection system”. In Intelligent Vehicles, pages 241–246.
[31] Papageorgiou, Constantine and Poggio, Tomaso. 1999. “A pattern classification approach to dynamical object detection”. In Proceedings of ICCV, pages 1223–1228.
[32] Papageorgiou, Constantine P., Oren, Michael, and Poggio, Tomaso, 1998. “A general framework for object detection”. In ICCV, pages 555–562.
[33] Pontil, Massimiliano and Verri, A., 1997. “Direct aspect-based 3-d object recognition”. In Int. Conf on Image Analysis and Processing, Firenze.
[34] Raudys, S. J. and Jain, A. K., 1991. “Small sample size effects in statistical pattern recognition: Recommendations for practitioners”. In IEEE Trans. on Pattern Analysis and Machine Intelligence, volume 13, pages 252–264.
[35] Roobaert, Danny and Hulle, Marc M. Van, 1999. “View-based 3d object recognition with support vector machines”. In IEEE Neural Networks for Signal Processing.
[36] Schlkopf, B., O Burges, and Vapnik, V, 1996. “Incorporating invariances in support vector learning machines”. In Articial Neural Networks — ICANN’96, volume 1112, pages 47–52, Berlin. Springer Lecture Notes in Computer Science.
65
[37] Tong, Simon and Chang, Edward, 2001. “Support vector machine active learning for image retrieval”. In ACM multimedia 2001, Ontario, Canada.
[38] Vannerem, P., Mller, K.R., Schlkopf, B., Smola, A., and Sldner-Rembold, S, 1999. “Classifying lep data with support vector algorithms”. In AIHENP’99.
[39] Vapnik, V, 1982. “Estimation of dependencies based on empirical data”. New York. Springer-Verlag.
[40] Vapnik, V, 1995. “The nature of statistical learning theory”. Berlin,. Springer-Verlag.
[41] Zhao, Qun and Principe, Jose, 1998. “Automatic target recognition with support vector machines”. In NIPS-98 Workshop on Large Margin Classifiers.
[42] Zien, Ratsch, Mika, Scholkopf, Lengauer, and Muller., 2000. “Engineering support vector machine kernels that recognize translation initiation sites”. BIOINF: Bioinformatics, 16.
[43] Hastie, T., Rosset, S., Tibshirani, R., and Zhu, J., 2004. “The Entire Regularization Path for the Support Vector Machine”. J. Machine Learning Research, vol. 5, pp. 1391-1415.
[44] Jain, A.K., and Vailaya, A. 1998. “Shape-Based Retrieval: A Case Study with Trademark Image Database”. Pattern Recognition, vol. 9, pp. 1369-1390.
[45] Manjunath, B., Wu, P., Newsam, S., and Shin, H., 2000. “A Texture Descriptor for Browsing and Similarity Retrieval”. J. Signal Processing: Image Comm., vol. 16, pp. 33-42.
[46] Rocchio, J., 1971. “Relevance Feedback in Information Retrieval”. The SMART Retrieval System: Experiments in Automatic Document Processing, pp. 313-323.
[47] Rui, Y., Huang, T.S., Ortega, M., and Mehrotra, S. , Sept. 1998. “Relevance Feedback: A Power Tool in Interactive Content-Based Image Retrieval”. IEEE Trans. Circuits and Systems for Video Technology, vol. 8, no. 5, pp. 644-655.
66
[48] Salton, G., and McGill, M.J., 1983. “Introduction to Modern Information Retrieval”. McGraw-Hill.
[49] Smeulders, A.W.M., Worring, M., Santini, S., Gupta, A., and Jain, R., Dec. 2000. “Content-Based Image Retrieval at the End of the Early Years”. IEEE Trans. Pattern Analysis and Machine Intelligence, vol. 22, no. 12, pp. 1349-1380.
[50] Smith, J., and Chang, S.-F., Nov. 1996. “Automated Image Retrieval Using Color and Texture”. IEEE Trans. Pattern Analysis and Machine Intelligence, vol. 18, no. 11.
[51] C.-C. Chang and C.-J. Lin, 2001. “LIBSVM: A Library for Support Vector Machines,” http://www.csie.ntu.edu.tw/~cjlin/libsvm.
67
function mosseFilter(params) { var _filter, _top, _bottom; var _fft; var _w,_h; var _im_part; var _arrlen; var _cc; var _image_array; this.psr_prev = undefined; this.peak_prev = undefined; var peak = 0.0; var updateable = false; if (!params) params = {}; // setup of canvas for drawing responses, if given if (params.drawResponse === undefined) { params.drawResponse = false; } else { if (params.drawResponse.tagName != 'CANVAS') { params.drawResponse = false; } else { var responseContext = params.drawResponse.getContext('2d'); } } if (params.psrThreshold === undefined) params.psrThreshold = 10; if (params.eta === undefined) params.eta = 0.10; if (params.convertToGrayscale === undefined) params.convertToGrayscale = true; this.load = function(filter) { // initialize filter width and height _w = filter.width; _h = filter.height; _arrlen = _w*_h; _filter = [filter.real, filter.imag]; // handling top and bottom when they're not present if (filter.top && filter.bottom) { updateable = true; _top = [filter.top.real, filter.top.imag]; _bottom = [filter.bottom.real, filter.bottom.imag]; } // initialize fft to given width _fft = new FFT(); _fft.init(filter.width); // set up temporary variables if(typeof Float64Array !== 'undefined') { _im_part = new Float64Array(_arrlen); _image_array = new Float64Array(_arrlen); } else {
BLOK KODE 1:
Tapis Korelasi MOSSE
68
_im_part = new Array(_arrlen); _image_array = new Array(_arrlen); } var canvas = document.createElement("canvas"); canvas.setAttribute('width', _w); canvas.setAttribute('height', _h); _cc = canvas.getContext('2d'); } this.init = function(w,h) { // initialize filter width and height for a blank filter _w = w; _h = h; _arrlen = _w*_h; _filter = [[],[]]; _top = [[],[]]; _bottom = [[],[]]; for (var i = 0;i < _arrlen;i++) { _filter[0][i] = 0; _filter[1][i] = 0; _top[0][i] = 0; _top[1][i] = 0; _bottom[0][i] = 0; _bottom[1][i] = 0; } updateable = true; // initialize fft to given width _fft = new FFT(); _fft.init(w); // set up temporary variables if(typeof Float64Array !== 'undefined') { _im_part = new Float64Array(_arrlen); } else { _im_part = new Array(_arrlen); } var canvas = document.createElement("canvas"); canvas.setAttribute('width', _w); canvas.setAttribute('height', _h); _cc = canvas.getContext('2d'); } // fft function this.fft = function(array) { // not in-place var cn = new Array(_arrlen); for (var i = 0;i < _arrlen;i++) { cn[i] = 0.0; } _fft.fft2d(array,cn) return [array, cn]; } // fft function this.fft_inplace = function(array) { // in-place
69
for (var i = 0;i < _arrlen;i++) { _im_part[i] = 0.0; } _fft.fft2d(array,_im_part) return [array, _im_part]; } this.ifft = function(rn, cn) { // in-place _fft.ifft2d(rn, cn); return rn; } // peak to sidelobe ratio function (optional) this.psr = function(array) { // proper var sum = 0; var max = 0; var maxpos = []; var sdo = 0; var val; for (var x = 0;x < _w;x++) { for (var y = 0;y < _h;y++) { val = array[(y*_w)+x]; sum += val; sdo += (val*val); if (max < val) { max = val; maxpos = [x,y]; } } } // subtract values around peak for (var x = -5;x < 6;x++) { for (var y = -5;y < 6;y++) { if (Math.sqrt(x*x+y*y) < 5) { val = array[((maxpos[1]+y)*_w)+(maxpos[0]+x)] sdo -= (val*val); sum -= val; } } } var mean = sum/array.length; var sd = Math.sqrt((sdo/array.length)-(mean*mean)); // get mean/variance of output around peak var psr = (max-mean)/sd; return psr; } this.getResponse = function(imageData) { // in-place // preprocess var prepImage = preprocess(imageData); prepImage = cosine_window(prepImage); // filter
70
var res = this.fft_inplace(prepImage); // elementwise multiplication with filter complex_mult_inplace(res, _filter); // do inverse 2d fft var filtered = this.ifft(res[0],res[1]); return filtered; } this.track = function(input, left, top, width, height, updateFilter, gaussianPrior, calcPSR) { // finds position of filter in input image if (!_filter) { console.log("Mosse-filter needs to be initialized or trained before starting tracking."); return false; } if (input.tagName == "VIDEO" || input.tagName == "IMG") { // scale selection according to original source image var videoLeft = Math.round((left/input.width)*input.videoWidth); var videoTop = Math.round((top/input.height)*input.videoHeight); var videoWidth = Math.round((width/input.width)*input.videoWidth); var videoHeight = Math.round((height/input.height)*input.videoHeight); _cc.drawImage(input, videoLeft, videoTop, videoWidth, videoHeight, 0, 0, _w, _h); } else if (input.tagName == "CANVAS") { _cc.drawImage(input, left, top, width, height, 0, 0, _w, _h); } var image = _cc.getImageData(0,0,_w,_h); var id = image.data; if (params.convertToGrayscale) { // convert to grayscale for (var i = 0;i < _arrlen;i++) { _image_array[i] = id[(4*i)]*0.3; _image_array[i] += id[(4*i)+1]*0.59; _image_array[i] += id[(4*i)+2]*0.11; } } else { // use only one channel for (var i = 0;i < _arrlen;i++) { _image_array[i] = id[(4*i)]; } } // preprocess var prepImage = preprocess(_image_array); prepImage = cosine_window(prepImage); // filter var res = this.fft_inplace(prepImage); // elementwise multiplication with filter
71
var nures = complex_mult(res, _filter); // do inverse 2d fft var filtered = this.ifft(nures[0],nures[1]); // find max and min var max = 0; var min = 0; var maxpos = []; //method using centered gaussian prior if (gaussianPrior) { var prior, dx, dy; var variance = 128; for (var x = 0;x < _w;x++) { for (var y = 0;y < _h;y++) { dx = x - _w/2; dy = y - _h/2; prior = Math.exp(-0.5*((dx*dx)+(dy*dy))/variance) if ((filtered[(y*_w)+x]*prior) > max) { max = filtered[(y*_w)+x]*prior; maxpos = [x,y]; } if (filtered[(y*_w)+x] < min) { min = filtered[(y*_w)+x]; } } } } else { for (var x = 0;x < _w;x++) { for (var y = 0;y < _h;y++) { if (filtered[(y*_w)+x] > max) { max = filtered[(y*_w)+x]; maxpos = [x,y]; } if (filtered[(y*_w)+x] < min) { min = filtered[(y*_w)+x]; } } } } this.peak_prev = max; if (params.drawResponse) { // draw response var diff = max-min; var dc = document.createElement('canvas'); dc.setAttribute('width', 32); dc.setAttribute('height', 32); var dcc = dc.getContext('2d'); var psci = dcc.createImageData(32, 32); var pscidata = psci.data; for (var j = 0;j < 32*32;j++) { //draw with priors //var val = filtered[j]*Math.exp(-0.5*(((j%_w - _w/2)*(j%_w -_w/2))+((Math.floor(j/_h)-(_h/2))*(Math.floor(j/_h)-(_h/2))))/128); var val = filtered[j]; val = Math.round((val+Math.abs(min))*(255/diff)); pscidata[j*4] = val; pscidata[(j*4)+1] = val; pscidata[(j*4)+2] = val;
72
pscidata[(j*4)+3] = 255; } dcc.putImageData(psci, 0, 0); responseContext.drawImage(dc, left, top, width, width); } if (calcPSR) { this.psr_prev = this.psr(filtered); } if (updateFilter) { if (!updateable) { console.log("The loaded filter does not support updating. Ignoring parameter 'updateFilter'."); } else { if (calcPSR) { var psr = this.psr_prev; } else { var psr = this.psr(filtered); } if (psr > params.psrThreshold) { // create target var target = []; var nux = maxpos[0]; var nuy = maxpos[1]; for (var x = 0;x < _w;x++) { for (var y = 0;y < _h;y++) { target[(y*_w)+x] = Math.exp(-(((x-nux)*(x-nux))+((y-nuy)*(y-nuy)))/(2*2)); } } //fft target target = this.fft(target); // create filter var res_conj = complex_conj(res); var fuTop = complex_mult(target,res_conj); var fuBottom = complex_mult(res,res_conj); // add up var eta = params.eta; for (var i = 0;i < _arrlen;i++) { _top[0][i] = eta*fuTop[0][i] + (1-eta)*_top[0][i]; _top[1][i] = eta*fuTop[1][i] + (1-eta)*_top[1][i]; _bottom[0][i] = eta*fuBottom[0][i] + (1-eta)*_bottom[0][i]; _bottom[1][i] = eta*fuBottom[1][i] + (1-eta)*_bottom[1][i]; } _filter = complex_div(_top,_bottom); } } } /*if (psr < 5) { maxpos = [_w/2,_h/2];
73
}*/ maxpos[0] = maxpos[0]*(width/_w); maxpos[1] = maxpos[1]*(width/_h); // check if output is strong enough // if not, return false? if (max < 0) { return false; } else { return maxpos; } } this.train = function(input, left, top, width, height) { if (!updateable) { console.log("The loaded filter does not support updating. Unable to do training."); return false; } if (input.tagName == "VIDEO" || input.tagName == "IMG") { // scale selection according to original source image var videoLeft = Math.round((left/input.width)*input.videoWidth); var videoTop = Math.round((top/input.height)*input.videoHeight); var videoWidth = Math.round((width/input.width)*input.videoWidth); var videoHeight = Math.round((height/input.height)*input.videoHeight); _cc.drawImage(input, videoLeft, videoTop, videoWidth, videoHeight, 0, 0, _w, _h); } else if (input.tagName == "CANVAS") { _cc.drawImage(input, left, top, width, height, 0, 0, _w, _h); } var image = _cc.getImageData(0,0,_w,_h); var id = image.data; // convert to grayscale for (var i = 0;i < _arrlen;i++) { _image_array[i] = id[(4*i)]*0.3; _image_array[i] += id[(4*i)+1]*0.59; _image_array[i] += id[(4*i)+2]*0.11; } // preprocess var prepImage = preprocess(_image_array); prepImage = cosine_window(prepImage); // create target var target = []; var nux = _w/2; var nuy = _h/2; for (var x = 0;x < _w;x++) { for (var y = 0;y < _h;y++) { target[(y*_w)+x] = Math.exp(-(((x-nux)*(x-nux))+((y-nuy)*(y-nuy)))/(2*2));
74
} } //fft target target = this.fft(target); // filter var res = this.fft(prepImage); // create filter var res_conj = complex_conj(res); var fuTop = complex_mult(target,res_conj); var fuBottom = complex_mult(res,res_conj); // add up var eta = params.eta; for (var i = 0;i < _arrlen;i++) { _top[0][i] = eta*fuTop[0][i] + (1-eta)*_top[0][i]; _top[1][i] = eta*fuTop[1][i] + (1-eta)*_top[1][i]; _bottom[0][i] = eta*fuBottom[0][i] + (1-eta)*_bottom[0][i]; _bottom[1][i] = eta*fuBottom[1][i] + (1-eta)*_bottom[1][i]; } _filter = complex_div(_top,_bottom); return true; } var preprocess = function(array) { // in-place // log adjusting for (var i = 0;i < _arrlen;i++) { array[i] = Math.log(array[i]+1); } // normalize to mean 0 and norm 1 var mean = 0; for (var i = 0;i < _arrlen;i++) { mean += array[i]; } mean /= _arrlen; for (var i = 0;i < _arrlen;i++) { array[i] -= mean; } var norm = 0.0; for (var i = 0;i < _arrlen;i++) { norm += (array[i]*array[i]); } norm = Math.sqrt(norm); for (var i = 0;i < _arrlen;i++) { array[i] /= norm; } return array; } var cosine_window = function(array) { // calculate rect cosine window (in-place)
75
var pos = 0; for (var i = 0;i < _w;i++) { for (var j = 0;j < _h;j++) { //pos = (i%_w)+(j*_w); var cww = Math.sin((Math.PI*i)/(_w-1)) var cwh = Math.sin((Math.PI*j)/(_h-1)) array[pos] = Math.min(cww,cwh)*array[pos]; pos++; } } return array; } var complex_mult = function(cn1, cn2) { // not in-place var re_part = new Array(_w); var im_part = new Array(_w); var nucn = [re_part, im_part]; for (var r = 0;r < _arrlen;r++) { nucn[0][r] = (cn1[0][r]*cn2[0][r]) - (cn1[1][r]*cn2[1][r]); nucn[1][r] = (cn1[0][r]*cn2[1][r]) + (cn1[1][r]*cn2[0][r]); } return nucn; } var complex_mult_inplace = function(cn1, cn2) { // in-place var temp1, temp2; for (var r = 0;r < _arrlen;r++) { temp1 = (cn1[0][r]*cn2[0][r]) - (cn1[1][r]*cn2[1][r]); temp2 = (cn1[0][r]*cn2[1][r]) + (cn1[1][r]*cn2[0][r]); cn1[0][r] = temp1; cn1[1][r] = temp2; } } var complex_conj = function(cn) { // not in-place (TODO) var nucn = [[],[]]; for (var i = 0;i < _arrlen;i++) { nucn[0][i] = cn[0][i] nucn[1][i] = -cn[1][i]; } return nucn; } var complex_div = function(cn1, cn2) { // not in-place (TODO) var nucn = [[],[]]; for (var r = 0;r < _arrlen;r++) { nucn[0][r] = ((cn1[0][r]*cn2[0][r])+(cn1[1][r]*cn2[1][r])) / ((cn2[0][r]*cn2[0][r]) + (cn2[1][r]*cn2[1][r])); nucn[1][r] = ((cn1[1][r]*cn2[0][r])-(cn1[0][r]*cn2[1][r])) / ((cn2[0][r]*cn2[0][r]) + (cn2[1][r]*cn2[1][r])); } return nucn;
<script> var cc = document.getElementById('image').getContext('2d'); var overlay = document.getElementById('overlay'); var overlayCC = overlay.getContext('2d'); var img = new Image(); img.onload = function() { cc.drawImage(img,0,0,625, 500); }; img.src = './media/test_bumper.jpg'; var ctrack = new clm.tracker({stopOnConvergence : true}); ctrack.init(pModel); stats = new Stats(); stats.domElement.style.position = 'absolute'; stats.domElement.style.top = '0px'; document.getElementById('container').appendChild( stats.domElement ); var drawRequest; function animate(box) { ctrack.start(document.getElementById('image'), box); drawLoop(); } function drawLoop() { drawRequest = requestAnimFrame(drawLoop); overlayCC.clearRect(0, 0, 720, 576); if (ctrack.getCurrentPosition()) { ctrack.draw(overlay); } } // detect if tracker fails to find a face document.addEventListener("clmtrackrNotFound", function(event) { ctrack.stop(); alert("The tracking had problems with finding a face in this image. Try selecting the face in the image manually.") }, false); // detect if tracker loses tracking of face
BLOK KODE 4:
Script Implementasi Constraint Local Models pada gambar
82
document.addEventListener("clmtrackrLost", function(event) { ctrack.stop(); alert("The tracking had problems converging on a face in this image. Try selecting the face in the image manually.") }, false); // detect if tracker has converged document.addEventListener("clmtrackrConverged", function(event) { document.getElementById('convergence').innerHTML = "CONVERGED"; document.getElementById('convergence').style.backgroundColor = "#00FF00"; // stop drawloop cancelRequestAnimFrame(drawRequest); }, false); // update stats on iteration document.addEventListener("clmtrackrIteration", function(event) { stats.update(); }, false); // manual selection of faces (with jquery imgareaselect plugin) function selectBox() { overlayCC.clearRect(0, 0, 720, 576); document.getElementById('convergence').innerHTML = ""; ctrack.reset(); $('#overlay').addClass('hide'); $('#image').imgAreaSelect({ handles : true, onSelectEnd : function(img, selection) { // create box var box = [selection.x1, selection.y1, selection.width, selection.height]; // do fitting animate(box); $('#overlay').removeClass('hide'); }, autoHide : true }); } // function to start showing images function loadImage() { if (fileList.indexOf(fileIndex) < 0) { var reader = new FileReader(); reader.onload = (function(theFile) { return function(e) {
83
// check if positions already exist in storage // Render thumbnail. var canvas = document.getElementById('image') var cc = canvas.getContext('2d'); var img = new Image(); img.onload = function() { if (img.height > 500 || img.width > 700) { var rel = img.height/img.width; var neww = 700; var newh = neww*rel; if (newh > 500) { newh = 500; neww = newh/rel; } canvas.setAttribute('width', neww); canvas.setAttribute('height', newh); cc.drawImage(img,0,0,neww, newh); } else { canvas.setAttribute('width', img.width); canvas.setAttribute('height', img.height); cc.drawImage(img,0,0,img.width, img.height); } } img.src = e.target.result; }; })(fileList[fileIndex]); reader.readAsDataURL(fileList[fileIndex]); overlayCC.clearRect(0, 0, 720, 576); document.getElementById('convergence').innerHTML = ""; ctrack.reset(); } } // set up file selector and variables to hold selections var fileList, fileIndex;
84
if (window.File && window.FileReader && window.FileList) { function handleFileSelect(evt) { var files = evt.target.files; fileList = []; for (var i = 0;i < files.length;i++) { if (!files[i].type.match('image.*')) { continue; } fileList.push(files[i]); } if (files.length > 0) { fileIndex = 0; } loadImage(); } document.getElementById('files').addEventListener('change', handleFileSelect, false); } else { $('#files').addClass("hide"); $('#loadimagetext').addClass("hide"); } </script>
<script> // when everything is ready, automatically start everything ? var vid = document.getElementById('videoel'); var overlay = document.getElementById('overlay'); var overlayCC = overlay.getContext('2d'); /*********** Setup of video/webcam and checking for webGL support *********/ var videoReady = false; var imagesReady = false; function enablestart() { if (videoReady && imagesReady) { var startbutton = document.getElementById('startbutton'); startbutton.value = "start"; startbutton.disabled = null; } } $(window).load(function() { imagesReady = true;
BLOK KODE 5:
Script Substitusi Wajah
85
enablestart(); }); var insertAltVideo = function(video) { if (supports_video()) { if (supports_ogg_theora_video()) { video.src = "../media/cap13_edit2.ogv"; } else if (supports_h264_baseline_video()) { video.src = "../media/cap13_edit2.mp4"; } else { return false; } //video.play(); return true; } else return false; } // check whether browser supports webGL var webGLContext; var webGLTestCanvas = document.createElement('canvas'); if (window.WebGLRenderingContext) { webGLContext = webGLTestCanvas.getContext('webgl') || webGLTestCanvas.getContext('experimental-webgl'); if (!webGLContext || !webGLContext.getExtension('OES_texture_float')) { webGLContext = null; } } if (webGLContext == null) { alert("Your browser does not seem to support WebGL. Unfortunately this face mask example depends on WebGL, so you'll have to try it in another browser. :("); } navigator.getUserMedia = navigator.getUserMedia || navigator.webkitGetUserMedia || navigator.mozGetUserMedia || navigator.msGetUserMedia; window.URL = window.URL || window.webkitURL || window.msURL || window.mozURL; // check for camerasupport if (navigator.getUserMedia) { // set up stream // chrome 19 shim var videoSelector = {video : true}; if (window.navigator.appVersion.match(/Chrome\/(.*?) /)) { var chromeVersion = parseInt(window.navigator.appVersion.match(/Chrome\/(\d+)\./)[1], 10); if (chromeVersion < 20) { videoSelector = "video"; } };
86
navigator.getUserMedia(videoSelector, function( stream ) { if (vid.mozCaptureStream) { vid.mozSrcObject = stream; } else { vid.src = (window.URL && window.URL.createObjectURL(stream)) || stream; } vid.play(); }, function() { insertAltVideo(vid); alert("There was some problem trying to fetch video from your webcam, using a fallback video instead."); }); } else { insertAltVideo(vid); alert("Your browser does not seem to support getUserMedia, using a fallback video instead."); } vid.addEventListener('canplay', function() {videoReady = true;enablestart();}, false); /*********** Code for face substitution *********/ var animationRequest; var positions; var ctrack = new clm.tracker(); ctrack.init(pModel); document.getElementById('selectmask').addEventListener('change', updateMask, false); function updateMask(el) { currentMask = parseInt(el.target.value, 10); var positions = ctrack.getCurrentPosition(vid); if (positions) { switchMasks(positions); } } function startVideo() { // start video vid.play(); // start tracking ctrack.start(vid); // start drawing face grid drawGridLoop(); } var fd = new faceDeformer(); fd.init(document.getElementById('webgl'));
[19,93,71,19], [19,0,71,19], [44,61,56,44], [60,61,56,60], [60,56,57,60], [60,59,57,60], [58,59,57,58], [58,59,50,58] ]; function drawGridLoop() { // get position of face positions = ctrack.getCurrentPosition(vid); overlayCC.clearRect(0, 0, 500, 375); if (positions) { // draw current grid ctrack.draw(overlay); } // check whether mask has converged var pn = ctrack.getConvergence(); if (pn < 0.4) { switchMasks(positions); } else { requestAnimFrame(drawGridLoop); } } function switchMasks(pos) { videocanvas.getContext('2d').drawImage(vid,0,0,videocanvas.width,videocanvas.height); // we need to extend the positions with new estimated points in order to get pixels immediately outside mask var newMaskPos = masks[images[currentMask]].slice(0); var newFacePos = pos.slice(0); var extInd = [0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,22,21,20,19]; var newp; for (var i = 0;i < 23;i++) { newp = []; newp[0] = (newMaskPos[extInd[i]][0]*1.3) - (newMaskPos[62][0]*0.3);// short for ((newMaskPos[extInd[i]][0]-newMaskPos[62][0])*1.1)+newMaskPos[62][0] newp[1] = (newMaskPos[extInd[i]][1]*1.3) - (newMaskPos[62][1]*0.3); newMaskPos.push(newp); newp = []; newp[0] = (newFacePos[extInd[i]][0]*1.3) - (newFacePos[62][0]*0.3); newp[1] = (newFacePos[extInd[i]][1]*1.3) - (newFacePos[62][1]*0.3); newFacePos.push(newp); } // also need to make new vertices incorporating area outside mask var newVertices = pModel.path.vertices.concat(extended_vertices);
103
// deform the mask we want to use to face form fd2.load(imageCanvases[images[currentMask]], newMaskPos, pModel, newVertices); fd2.draw(newFacePos); // and copy onto new canvas newcanvas.getContext('2d').drawImage(document.getElementById('webgl2'),0,0); // create masking var tempcoords = positions.slice(0,18); tempcoords.push(positions[21]); tempcoords.push(positions[20]); tempcoords.push(positions[19]); createMasking(maskcanvas, tempcoords); /*document.body.appendChild(newcanvas); document.body.appendChild(videocanvas); document.body.appendChild(maskcanvas); debugger;*/ // do poisson blending Poisson.load(newcanvas, videocanvas, maskcanvas, function() { var result = Poisson.blend(30, 0, 0); // render to canvas newcanvas.getContext('2d').putImageData(result, 0, 0); // get mask var maskname = Object.keys(masks)[currentMask]; fd.load(newcanvas, pos, pModel); requestAnimFrame(drawMaskLoop); }); } function drawMaskLoop() { // get position of face positions = ctrack.getCurrentPosition(); /*for (var i = 0;i < positions.length;i++) { positions[i][1] += 1; }*/ overlayCC.clearRect(0, 0, 400, 300); if (positions) { // draw mask on top of face fd.draw(positions); } animationRequest = requestAnimFrame(drawMaskLoop); } function createMasking(canvas, modelpoints) {
104
// fill canvas with black var cc = canvas.getContext('2d'); cc.fillStyle="#000000"; cc.fillRect(0,0,canvas.width, canvas.height); cc.beginPath(); cc.moveTo(modelpoints[0][0], modelpoints[0][1]); for (var i = 1;i < modelpoints.length;i++) { cc.lineTo(modelpoints[i][0], modelpoints[i][1]); } cc.lineTo(modelpoints[0][0], modelpoints[0][1]); cc.closePath(); cc.fillStyle="#ffffff"; cc.fill(); } /*********** Code for stats **********/ stats = new Stats(); stats.domElement.style.position = 'absolute'; stats.domElement.style.top = '0px'; document.getElementById('container').appendChild( stats.domElement ); document.addEventListener("clmtrackrIteration", function(event) { stats.update(); }, false); </script>
<script> var vid = document.getElementById('videoel'); var overlay = document.getElementById('overlay'); var overlayCC = overlay.getContext('2d'); var ctrack = new clm.tracker(); ctrack.init(pModel); stats = new Stats(); stats.domElement.style.position = 'absolute'; stats.domElement.style.top = '0px'; document.getElementById('container').appendChild( stats.domElement ); function enablestart() { var startbutton = document.getElementById('startbutton'); startbutton.value = "start"; startbutton.disabled = null; } var insertAltVideo = function(video) { if (supports_video()) {
BLOK KODE 6:
Script Masking Wajah
105
if (supports_ogg_theora_video()) { video.src = "./media/cap13_edit2.ogv"; } else if (supports_h264_baseline_video()) { video.src = "./media/cap13_edit2.mp4"; } else { return false; } //video.play(); return true; } else return false; } // check whether browser supports webGL var webGLContext; var webGLTestCanvas = document.createElement('canvas'); if (window.WebGLRenderingContext) { webGLContext = webGLTestCanvas.getContext('webgl') || webGLTestCanvas.getContext('experimental-webgl'); if (!webGLContext || !webGLContext.getExtension('OES_texture_float')) { webGLContext = null; } } if (webGLContext == null) { alert("Your browser does not seem to support WebGL. Unfortunately this face mask example depends on WebGL, so you'll have to try it in another browser. :("); } navigator.getUserMedia = navigator.getUserMedia || navigator.webkitGetUserMedia || navigator.mozGetUserMedia || navigator.msGetUserMedia; window.URL = window.URL || window.webkitURL || window.msURL || window.mozURL; // check for camerasupport if (navigator.getUserMedia) { // set up stream // chrome 19 shim var videoSelector = {video : true}; if (window.navigator.appVersion.match(/Chrome\/(.*?) /)) { var chromeVersion = parseInt(window.navigator.appVersion.match(/Chrome\/(\d+)\./)[1], 10); if (chromeVersion < 20) { videoSelector = "video"; } }; navigator.getUserMedia(videoSelector, function( stream ) { if (vid.mozCaptureStream) { vid.mozSrcObject = stream; } else { vid.src = (window.URL && window.URL.createObjectURL(stream)) || stream; } vid.play(); }, function() { insertAltVideo(vid); document.getElementById('gum').className = "hide"; document.getElementById('nogum').className = "nohide"; alert("There was some problem trying to fetch video from your webcam, using a fallback video instead."); }); } else { insertAltVideo(vid) document.getElementById('gum').className = "hide"; document.getElementById('nogum').className = "nohide"; alert("Your browser does not seem to support getUserMedia, using a fallback video instead."); } vid.addEventListener('canplay', enablestart, false);
106
document.getElementById('selectmask').addEventListener('change', updateMask, false); function updateMask(el) { currentMask = parseInt(el.target.value, 10); switchMasks(); } function startVideo() { // start video vid.play(); // start tracking ctrack.start(vid); // start drawing face grid drawGridLoop(); } var positions; var fd = new faceDeformer(); fd.init(document.getElementById('webgl')); //var bieberpos = [[115.9752686028232,328.6220466908972],[119.22873121946967,374.40858852922236],[131.1565130945076,417.23833371292824],[147.46691862513703,458.8532123608701],[169.12631494681284,491.1972025630235],[195.43904217855416,516.328978933631],[225.12865446493407,535.9062523012337],[262.04556382915666,540.3069324850155],[300.94141109040174,527.8502399147961],[332.9603108915372,502.45220152142446],[358.8360460728861,471.19379837598467],[376.30594053223126,432.7368076223554],[382.67017562895774,386.092455079847],[382.9572691840467,340.6309871594118],[373.9218117623584,294.7317621266673],[336.1771287095879,277.33615469931993],[309.0591744841313,265.48318334798023],[280.18008080721654,270.41133608650136],[256.43572723795205,288.00624486316775],[132.78340927208725,302.3508622540975],[152.12755213329575,285.64501141366554],[179.00521938859092,283.71128940592473],[205.2906738672715,295.0025921899086],[153.280095626718,326.6176205427562],[173.66825536827957,312.37635516179034],[200.5039461913669,321.80135395397144],[176.4252911165302,331.5053440165448],[175.60476729990694,320.7103852530686],[320.09549369069657,304.98353187039095],[293.8708067688545,296.76097677136033],[271.58562891677826,313.04623730551765],[297.0041924786207,316.0129930023768],[295.5198902690135,305.2334114426537],[219.39189145138596,322.52490657195426],[213.12903160458814,372.68944673895106],[204.25378527943315,395.19379951207986],[216.42423446106187,407.4119870829318],[242.53049164091706,409.5633258220383],[271.44166574243314,400.8594406366267],[281.0747413420262,385.33753840829905],[264.93761588662034,366.0082686027026],[248.4222279939238,318.65718124206103],[221.19696050353386,400.1917656470539],[261.194844263039,394.3039377608819],[205.58562543311808,454.0404194376248],[219.45570688767742,443.2933320382955],[235.11772368281123,437.7856722052561],[247.04484871943168,439.0481001020766],[258.89570167366736,434.78235106489905],[278.09912572601576,436.0808959514672],[299.3034775622639,442.54677422653293],[287.1187997918484,455.81576684891434],[271.34249957002703,465.51172329290904],[251.61268198682447,470.44097715445434],[232.73570674290363,470.1580146696677],[218.10425477812518,464.10041259051224],[228.1409097022435,453.68187695329203],[249.6936987242403,453.78342049724876],[272.6989984571775,448.2156278276872],[272.0110524437053,444.79167221837804],[248.77651531852348,448.8688363646738],[227.509537176152,450.245536680183],[237.9908602824163,390.1923398762123],[160.91646595859757,317.33744947123716],[188.7840782811474,313.8256705835899],[189.05067958859877,327.25046064429824],[163.55409188544704,330.4344482791597],[308.5376365048648,298.0766114500345],[279.84528286898836,302.2825309865559],[283.62066631586,315.20905218987537],[309.749050119264,311.6663773937525]]; //var bieberpos2 = [[101.56864876894927,233.18862451146063],[103.94483672830893,264.7046059637433],[111.5648760614713,292.9868982438346],[121.60817984472148,320.6033955384772],[135.51459988174054,341.80331615737293],[152.82503856414286,357.93865673417645],[172.7334093282495,369.7555151544583],[197.69694806265264,372.8908642984119],[222.8053964543867,365.21949767570914],[242.40546640781133,350.0527677685787],[258.17324630755496,33
45823523985],[269.1473100017029,428.92524246489165],[256.3562958006237,421.3232920714367],[269.4689541559383,409.5609803328374],[288.9859238876932,410.32998112652183],[306.1403256243275,411.3077976017484],[307.73772138569666,411.00947047307966],[288.5537974824452,410.51396287362655],[269.7179313684785,409.79854206584145],[293.13908085531165,360.2044576609231],[210.24669344926002,268.1362929595334],[244.33001418358253,272.06529726630106],[237.37014577148472,289.8158253810601],[212.28729137033707,286.8846525992707],[364.4764146636024,276.60992312858446],[332.73309300337735,280.1921291112648],[336.47694784065465,295.57941207015807],[365.2216557008562,291.9943008746264]], "cage2" : [[96.81941282528646,268.6563333055432],[106.75675954633661,329.1587405365555],[119.76815459937384,379.4896985493418],[136.07940076941458,425.9492772057105],[161.2808692110661,457.61169473264835],[186.04894852923297,485.6759001579113],[218.4426767235838,511.0714335097357],[260.06499742347034,523.1545996578884],[300.06377090251993,510.61216792938615],[337.5694959005854,468.82896175985],[358.97922192378047,441.54181864835476],[379.42084177310676,403.390743126405],[388.7955321567646,351.3090658772298],[390.4262385647278,299.3698133324318],[384.11810900892965,242.91856536650718],[348.70738406950056,224.9829932049514],[321,222],[284,222],[248.86954256992664,228.19206802513366],[119.91233030390185,255.38702736145385],[138,245],[175,236],[211.38447558444696,237.17956241438634],[144.4884094882825,271.0334533280929],[166.20253053976617,258.5182260687953],[190.76818628874074,264.72493789715475],[166.3651367856651,273.4746395006701],[167.80450182394694,265.0556706110155],[324.5406048528901,251.04296112395667],[299.7419762994943,241.35048431345442],[272.0486344446429,254.37413342811146],[300.2779904213152,258.21350699061486],[299.7261402367746,247.52288292547877],[230,247],[202.82098590251388,333.63541920962166],[197.36529740216793,360.6074799565433],[211.93043020653712,374.7216105521087],[243.91457342932796,376.61574931741393],[273.7931176105319,368.54185553932047],[283.1924422789671,346.10700000116907],[273.21255878744284,326.3419941919277],[235,309],[216.08956463539755,366.1198047818831],[262.38157625268843,360.4765024368325],[200.65672420260339,425.7113072142362],[210.59591704137958,418.8310789950973],[226.72952280292276,414.1586736027959],[245.26202591934208,416.9013315273323],[261.6743086310934,412.2506112472961],[283.3509308337543,410.8975165060922],[302.2287007716769,414.3759049856237],[288.05687218005096,428.64611508851056],[272.9046262998521,439.81519003757444],[251.37714128101143,448.0168626101829],[229.03794885867393,446.9574815880215],[217.27491143676224,438.10808744290716],[225.27828463087235,425.86527765147576],[246.089531122415,426.43509210786846],[272.14938117327404,421.7534010147635],[271.81608729443224,421.5900960094701],[246.87299073434986,427.22889777615507],[225.65210985383266,426.21786917122313],[239.24882409629814,356.7923548552414],[152.34433274214945,262.7826049480205],[179.48599280195447,258.6243674505216],[180.06624281569137,269.6029915273643],[153.926296458539,274.75536491866694],[312.6407607999811,242.7049854510107],[282.89141140599133,245.36953091106633],[285.6577700037131,257.30455480892334],[314.4040909797777,256.634302341433]] }; var currentMask = 0; var animationRequest; function drawGridLoop() { // get position of face positions = ctrack.getCurrentPosition(vid); overlayCC.clearRect(0, 0, 500, 375); if (positions) { // draw current grid ctrack.draw(overlay); } // check whether mask has converged var pn = ctrack.getConvergence(); if (pn < 0.4) { switchMasks();
115
requestAnimFrame(drawMaskLoop); } else { requestAnimFrame(drawGridLoop); } } function switchMasks() { // get mask var maskname = Object.keys(masks)[currentMask]; fd.load(document.getElementById(maskname), masks[maskname], pModel); } function drawMaskLoop() { // get position of face positions = ctrack.getCurrentPosition(); overlayCC.clearRect(0, 0, 400, 300); if (positions) { // draw mask on top of face fd.draw(positions); } animationRequest = requestAnimFrame(drawMaskLoop); } document.addEventListener("clmtrackrIteration", function(event) { stats.update(); }, false); </script>
<script> var vid = document.getElementById('videoel'); var overlay = document.getElementById('overlay'); var overlayCC = overlay.getContext('2d'); var ctrack = new clm.tracker(); ctrack.init(pModel); stats = new Stats(); stats.domElement.style.position = 'absolute'; stats.domElement.style.top = '0px'; document.getElementById('container').appendChild( stats.domElement ); function enablestart() { var startbutton = document.getElementById('startbutton'); startbutton.value = "start"; startbutton.disabled = null; } var insertAltVideo = function(video) { if (supports_video()) { if (supports_ogg_theora_video()) { video.src = "./media/franck.ogv"; } else if (supports_h264_baseline_video()) { alert("no mp4 video :("); //video.src = "./media/capture4.mp4"; } else { return false; } //video.play(); return true; } else return false; } var insertAltImage = function() { var canvas = document.getElementById('canvasel'); var cc = canvas.getContext('2d'); var
BLOK KODE 7:
Script Deformasi Realtime Wajah
116
img = new Image(); img.onload = function() { cc.drawImage(img, 0, 0, 370, 288); }; img.src = './media/franck_02221.jpg'; vid.className = "hide"; vid = canvas; canvas.className = "nohide"; var startbutton = document.getElementById('startbutton'); startbutton.onclick = function() { ctrack.start(vid); drawLoop(); } startbutton.value = "start"; startbutton.disabled = null; } // check whether browser supports webGL var webGLContext; var webGLTestCanvas = document.createElement('canvas'); if (window.WebGLRenderingContext) { webGLContext = webGLTestCanvas.getContext('webgl') || webGLTestCanvas.getContext('experimental-webgl'); if (!webGLContext || !webGLContext.getExtension('OES_texture_float')) { webGLContext = null; } } if (webGLContext == null) { alert("Your browser does not seem to support WebGL. Unfortunately this face deformation example depends on WebGL, so you'll have to try it in another browser. :("); } navigator.getUserMedia = navigator.getUserMedia || navigator.webkitGetUserMedia || navigator.mozGetUserMedia || navigator.msGetUserMedia; window.URL = window.URL || window.webkitURL || window.msURL || window.mozURL; // check for camerasupport if (navigator.getUserMedia) { // set up stream var videoSelector = {video : true}; if (window.navigator.appVersion.match(/Chrome\/(.*?) /)) { var chromeVersion = parseInt(window.navigator.appVersion.match(/Chrome\/(\d+)\./)[1], 10); if (chromeVersion < 20) { videoSelector = "video"; } }; navigator.getUserMedia(videoSelector, function( stream ) { if (vid.mozCaptureStream) { vid.mozSrcObject = stream; } else { vid.src = (window.URL && window.URL.createObjectURL(stream)) || stream; } vid.play(); }, function() { //insertAltVideo(vid); insertAltImage(); document.getElementById('gum').className = "hide"; document.getElementById('nogum').className = "nohide"; alert("There was some problem trying to fetch video from your webcam, using a static image instead."); }); } else { insertAltImage(); //insertAltVideo(vid); document.getElementById('gum').className = "hide"; document.getElementById('nogum').className =
117
"nohide"; alert("Your browser does not seem to support getUserMedia, using a static image instead."); } vid.addEventListener('canplay', enablestart, false); function startVideo() { // start video vid.play(); // start tracking ctrack.start(vid); //start drawing faces drawLoop(); } var positions; var fd = new faceDeformer(); fd.init(document.getElementById('webgl')); document.addEventListener("clmtrackrIteration", function(event) { stats.update(); }, false); function drawLoop() { // track in video positions = ctrack.getCurrentPosition(); overlayCC.clearRect(0, 0, 720, 576); if (positions) { ctrack.draw(overlay); } // hide buttons elem = document.getElementById('buttons'); elem.setAttribute('class', 'hide'); // show message var scoreel = document.getElementById('score'); scoreel.innerHTML = "Please keep head still while model fits"; var pn = ctrack.getConvergence(); if (pn < 1.8) { requestAnimFrame(setupFaceDeformation); scoreel.innerHTML = ""; if (vid.tagName == "VIDEO") { vid.pause(); } } else { requestAnimFrame(drawLoop); } } var ph, gui; var rotation = 0; var scale = 3; var xOffset = -10; var yOffset = 0; function setupFaceDeformation() { // draw face deformation model positions = ctrack.getCurrentPosition(); overlayCC.clearRect(0, 0, 720, 576); ctrack.draw(overlay); fd.load(vid, positions, pModel); fd.draw(positions); // hide video var elem = document.getElementById('container'); elem.setAttribute('class', 'hide'); // show facial deformation element elem = document.getElementById('webglcontainer'); elem.setAttribute('class', 'nohide'); // hide message element document.getElementById('score').setAttribute('class', 'hide'); // set up controls ph = new parameterHolder(); gui = new dat.GUI(); var guiSelect = gui.add(ph, 'presets', presets); var gui1 = gui.add(ph, 'param1', -50, 50).listen(); var gui2 = gui.add(ph, 'param2', -20, 20).listen();
118
var gui3 = gui.add(ph, 'param3', -20, 20).listen(); var gui4 = gui.add(ph, 'param4', -20, 20).listen(); var gui5 = gui.add(ph, 'param5', -20, 20).listen(); var gui6 = gui.add(ph, 'param6', -20, 20).listen(); var gui7 = gui.add(ph, 'param7', -20, 20).listen(); var gui8 = gui.add(ph, 'param8', -20, 20).listen(); var gui9 = gui.add(ph, 'param9', -20, 20).listen(); var gui10 = gui.add(ph, 'param10', -20, 20).listen(); var gui11 = gui.add(ph, 'param11', -20, 20).listen(); var gui12 = gui.add(ph, 'param12', -20, 20).listen(); var gui13 = gui.add(ph, 'param13', -20, 20).listen(); var gui14 = gui.add(ph, 'param14', -20, 20).listen(); var gui15 = gui.add(ph, 'param15', -20, 20).listen(); var gui16 = gui.add(ph, 'param16', -20, 20).listen(); var gui17 = gui.add(ph, 'param17', -20, 20).listen(); var gui18 = gui.add(ph, 'param18', -20, 20).listen(); var gui19 = gui.add(ph, 'param19', -20, 20).listen(); var gui20 = gui.add(ph, 'param20', -20, 20).listen(); var guiGrid = gui.add(ph, 'draw_grid', false); var guiFace = gui.add(ph, 'draw_face', true); gui1.onChange(drawDeformedFace); gui2.onChange(drawDeformedFace); gui3.onChange(drawDeformedFace); gui4.onChange(drawDeformedFace); gui5.onChange(drawDeformedFace); gui6.onChange(drawDeformedFace); gui7.onChange(drawDeformedFace); gui8.onChange(drawDeformedFace); gui9.onChange(drawDeformedFace); gui10.onChange(drawDeformedFace); gui11.onChange(drawDeformedFace); gui12.onChange(drawDeformedFace); gui13.onChange(drawDeformedFace); gui14.onChange(drawDeformedFace); gui15.onChange(drawDeformedFace); gui16.onChange(drawDeformedFace); gui17.onChange(drawDeformedFace); gui18.onChange(drawDeformedFace); gui19.onChange(drawDeformedFace); gui20.onChange(drawDeformedFace); guiSelect.onChange(switchDeformedFace); guiGrid.onChange(drawDeformedFace); guiFace.onChange(drawDeformedFace); drawDeformedFace(); } function drawDeformedFace() { // draw model var parameters = ctrack.getCurrentParameters(); parameters[0] = scale*Math.cos(rotation)-1; parameters[1] = scale*Math.sin(rotation); parameters[2] = xOffset; parameters[3] = yOffset; parameters[0+4] = ph.param1; parameters[1+4] = ph.param2; parameters[2+4] = ph.param3; parameters[3+4] = ph.param4; parameters[4+4] = ph.param5;
<script> var vid = document.getElementById('videoel'); var overlay = document.getElementById('overlay'); var overlayCC = overlay.getContext('2d'); /********** check and set up video/webcam **********/ function enablestart() { var startbutton = document.getElementById('startbutton'); startbutton.value = "start"; startbutton.disabled = null; } /*var insertAltVideo = function(video) { if (supports_video()) { if (supports_ogg_theora_video()) { video.src = "../media/cap12_edit.ogv"; } else if (supports_h264_baseline_video()) {
BLOK KODE 8:
Script Deteksi Emosi Wajah
121
video.src = "../media/cap12_edit.mp4"; } else { return false; } //video.play(); return true; } else return false; }*/ navigator.getUserMedia = navigator.getUserMedia || navigator.webkitGetUserMedia || navigator.mozGetUserMedia || navigator.msGetUserMedia; window.URL = window.URL || window.webkitURL || window.msURL || window.mozURL; // check for camerasupport if (navigator.getUserMedia) { // set up stream var videoSelector = {video : true}; if (window.navigator.appVersion.match(/Chrome\/(.*?) /)) { var chromeVersion = parseInt(window.navigator.appVersion.match(/Chrome\/(\d+)\./)[1], 10); if (chromeVersion < 20) { videoSelector = "video"; } }; navigator.getUserMedia(videoSelector, function( stream ) { if (vid.mozCaptureStream) { vid.mozSrcObject = stream; } else { vid.src = (window.URL && window.URL.createObjectURL(stream)) || stream; } vid.play(); }, function() { //insertAltVideo(vid); alert("There was some problem trying to fetch video from your webcam. If you have a webcam, please make sure to accept when the browser asks for access to your webcam."); }); } else { //insertAltVideo(vid); alert("This demo depends on getUserMedia, which your browser does not seem to support. :("); } vid.addEventListener('canplay', enablestart, false); /*********** setup of emotion detection *************/ var ctrack = new clm.tracker({useWebGL : true}); ctrack.init(pModel);
122
function startVideo() { // start video vid.play(); // start tracking ctrack.start(vid); // start loop to draw face drawLoop(); } function drawLoop() { requestAnimFrame(drawLoop); overlayCC.clearRect(0, 0, 400, 300); //psrElement.innerHTML = "score :" + ctrack.getScore().toFixed(4); if (ctrack.getCurrentPosition()) { ctrack.draw(overlay); } var cp = ctrack.getCurrentParameters(); var er = ec.meanPredict(cp); if (er) { updateData(er); for (var i = 0;i < er.length;i++) { if (er[i].value > 0.4) { document.getElementById('icon'+(i+1)).style.visibility = 'visible'; } else { document.getElementById('icon'+(i+1)).style.visibility = 'hidden'; } } } } var ec = new emotionClassifier(); ec.init(emotionModel); var emotionData = ec.getBlank(); /************ d3 code for barchart *****************/ var margin = {top : 20, right : 20, bottom : 10, left : 40}, width = 400 - margin.left - margin.right, height = 100 - margin.top - margin.bottom; var barWidth = 30; var formatPercent = d3.format(".0%"); var x = d3.scale.linear() .domain([0, ec.getEmotions().length]).range([margin.left, width+margin.left]); var y = d3.scale.linear()