Anda di halaman 1dari 159

www.it-ebooks.

info
Menguasai OpenCV
dengan Proyek Visi
Komputer Praktis

Langkah-langkah tutorial untuk memecahkan umum


dunia nyata masalah visi komputer desktop atau
mobile, dari augmented reality dan nomor
pengakuan plat untuk pengenalan wajah dan kepala
3D pelacakan

Daniel Lelis Baggio


Shervin Emami
David Millán Escriva
Khvedchenia Ievgen
Naureen Mahmood
Jason Saragih
Roy Shilkrot

BIRMINGHAM - MUMBAI
www.it-ebooks.info
Menguasai OpenCV dengan
Proyek Visi Komputer Praktis
Copyright © 2012 Packt Publishing

Seluruh hak cipta. Tidak ada bagian dari buku ini dapat direproduksi, disimpan
dalam sistem pencarian, atau ditransmisikan dalam bentuk apapun atau dengan
cara apapun, tanpa izin tertulis dari penerbit, kecuali dalam kasus kutipan
singkat tertanam dalam artikel kritis atau ulasan.
Setiap upaya telah dilakukan dalam penyusunan buku ini untuk memastikan
keakuratan informasi yang disajikan. Namun, informasi yang terkandung dalam
buku ini dijual tanpa jaminan, baik tersurat maupun tersirat. Baik penulis, atau
Packt Publishing, dan dealer dan distributor akan dapat dimintai tanggung
jawab untuk kerugian yang disebabkan atau diduga disebabkan langsung atau
tidak langsung oleh buku ini.
Packt Publishing telah berupaya untuk memberikan informasi merek dagang tentang
semua perusahaan dan produk yang disebutkan dalam buku ini dengan penggunaan
yang tepat dari ibukota. Namun, Packt Publishing tidak dapat menjamin keakuratan
informasi ini.

Pertama kali diterbitkan: Desember 2012

Produksi Referensi: 2231112

Diterbitkan oleh Packt Publishing Ltd


Livery Tempat
35 Livery Jalan
Birmingham B3 2PB, UK.

ISBN 978-1-84951-782-9
www.packtpub.com

Menutupi Image by Neha Rajappan (neha.rajappan1@gmail.com)


www.it-ebooks.info
kredit

penulis Salin Editor


Daniel Lelis Baggio Brandt D'Mello
Shervin Emami aditya Nair
David Millán Escriva Alfida Paiva
Khvedchenia Ievgen
Naureen Mahmood Koordinator proyek
priya Sharma
Jason Saragih
Roy Shilkrot
proofreader
Chris Brown
Reviewer
Martin Diver
Kirill Kornyakov
Luis Díaz Más
indexer
Sebastian Montabone
Hemangini Bari
Tejal Soni
akuisisi Editor
Rekha Nair
Usha Iyer

Graphics
Memimpin Teknis Editor
Valentina D'silva
Ankita Shashi
Aditi Gajjar

Editor teknis
Sharvari Baet Koordinator Produksi
Arvindkumar Gupta
Prashant Salvi

penutup Kerja
Arvindkumar Gupta

www.it-ebooks.info
Tentang Penulis

Daniel Lelis Baggio mulai karyanya dalam visi komputer melalui medis
pengolahan citra di INCOR (Instituto melakukan Coração - Heart Institute) di São Paulo,
di mana ia bekerja dengan segmentasi USG gambar intra-vaskular. Dari dulu,
ia telah difokuskan pada GPGPU dan porting algoritma segmentasi untuk bekerja dengan
CUDA NVIDIA. Ia juga terjun ke enam derajat pelacakan kepala kebebasan
dengan kelompok user interface alami melalui EHCI proyek yang disebut
(http://code.google.com/p/ EHCI /). Dia sekarang bekerja untuk Angkatan Udara Brasil.

Saya ingin berterima kasih kepada Tuhan atas kesempatan bekerja


dengan visi komputer. Saya mencoba untuk memahami algoritma
indah Dia telah menciptakan bagi kita untuk melihat. Saya juga
berterima kasih kepada keluarga saya, dan terutama istri saya,
untuk semua dukungan mereka sepanjang perkembangan buku.
Saya ingin mendedikasikan buku ini untuk anak saya Stefano.

Shervin Emami (Lahir di Iran) belajar sendiri elektronik dan robotika hobi
selama awal remaja di Australia. Sambil membangun robot pertama pada usia
15, ia belajar bagaimana RAM dan CPU bekerja. Dia begitu kagum dengan
konsep yang ia segera merancang dan membangun sebuah motherboard Z80
secara keseluruhan untuk mengontrol robot, dan menulis semua software murni
dalam kode mesin biner menggunakan dua tombol push untuk 0s dan 1s. Setelah
mengetahui bahwa komputer dapat diprogram dengan cara lebih mudah seperti
bahasa assembly dan bahkan kompiler tingkat tinggi, Shervin menjadi
kecanduan untuk pemrograman komputer dan telah pemrograman desktop,
robot, dan smartphone hampir setiap hari sejak itu. Selama akhir remaja ia
menciptakan Draw3D (http://draw3d.shervinemami.info/), Pembuat model
3D dengan 30.000 baris dioptimalkan C dan kode assembly yang diberikan grafis
3D lebih cepat dari semua alternatif komersial waktu; tapi ia kehilangan minat
dalam pemrograman grafis ketika akselerasi perangkat keras 3D menjadi
tersedia.
www.it-ebooks.info
Di Universitas, Shervin mengambil subjek pada visi komputer dan menjadi sangat
tertarik di dalamnya; jadi untuk tesis pertamanya pada tahun 2003 ia menciptakan
program deteksi wajah real-time berdasarkan Eigenfaces, menggunakan OpenCV
(beta 3) untuk input kamera. Untuk tesis masternya pada tahun 2005 ia
menciptakan sistem navigasi visual untuk beberapa robot mobile menggunakan
OpenCV (v0.96). Dari tahun 2008, ia bekerja sebagai freelance Computer Vision
Developer di Abu Dhabi dan Filipina, menggunakan OpenCV untuk sejumlah
besar proyek-proyek komersial jangka pendek yang mencakup:
• Mendeteksi wajah menggunakan Haar atau Eigenfaces
• Mengenali wajah menggunakan Neural Networks, Ehmm, atau Eigenfaces
• Mendeteksi posisi 3D dan orientasi wajah dari satu foto menggunakan AAM
dan Posit
• Berputar wajah dalam 3D menggunakan hanya satu foto
• Wajah preprocessing dan pencahayaan buatan menggunakan segala arah 3D dari satu
foto
• pengakuan jenis kelamin
• pengenalan ekspresi wajah
• deteksi kulit
• deteksi iris
• deteksi murid
• pelacakan mata-tatapan
• pelacakan Visual-saliency
• pencocokan histogram
• deteksi tubuh ukuran
• Shirt dan bikini deteksi
• pengakuan uang
• stabilisasi video
• Pengenalan wajah pada iPhone
• Pengakuan makanan di iPhone
• Berbasis penanda augmented reality pada iPhone (kedua-tercepat iPhone augmented
aplikasi kenyataannya pada saat itu).
www.it-ebooks.info
OpenCV itu meletakkan makanan di atas meja untuk keluarga Shervin, jadi dia
mulai memberikan kembali kepada OpenCV melalui saran reguler di forum dan
dengan posting OpenCV tutorial gratis di website-nya (
http://www.shervinemami.info/openCV.html). Pada tahun 2011, ia menghubungi
para pemilik situs OpenCV gratis lainnya untuk menulis buku ini. Dia juga mulai
bekerja pada optimasi visi komputer untuk perangkat mobile di NVIDIA, bekerja
sama dengan pengembang OpenCV resmi untuk menghasilkan versi yang
dioptimalkan dari OpenCV untuk Android. Pada tahun 2012, ia juga bergabung
dengan komite Khronos OpenVL untuk standardisasi percepatan hardware visi
komputer untuk perangkat mobile, di mana OpenCV akan berbasis di masa depan.

Saya berterima kasih kepada Gay istri saya dan saya Luna bayi
untuk bertahan stres sementara aku juggled waktu antara buku ini,
bekerja fulltime, dan berkeluarga. Saya juga berterima kasih kepada
para pengembang OpenCV, yang bekerja keras selama bertahun-
tahun untuk menyediakan produk berkualitas tinggi secara gratis.

David Millán Escriva berusia delapan tahun ketika ia menulis program


pertama pada 8.086 PC dengan bahasa Basic, yang memungkinkan plotting 2D
persamaan dasar. Pada tahun 2005, ia selesai studinya di IT melalui Universitat
Politécnica de Valencia dengan pujian dalam interaksi manusia-komputer yang
didukung oleh visi komputer dengan OpenCV (v0.96). Dia memiliki tugas akhir
berdasarkan hal ini dan diterbitkan pada HCI Spanyol kongres. Dia berpartisipasi
dalam Blender, open source, proyek 3D-perangkat lunak, dan bekerja di
Plumiferos nya komersial pertama film - voladoras Aventuras sebagai Computer
Graphics Software Developer.
David kini memiliki lebih dari 10 tahun pengalaman di IT, dengan
pengalaman dalam visi komputer, komputer grafis, dan pengenalan pola,
bekerja pada proyek yang berbeda dan startups, menerapkan
pengetahuannya tentang visi komputer, pengenalan karakter optik, dan
augmented reality. Dia adalah penulis dari "DamilesBlog"
(http://blog.damiles.com), Di mana ia menerbitkan artikel penelitian dan
tutorial tentang OpenCV, visi komputer pada umumnya, dan Optical
Character Recognition algoritma.
www.it-ebooks.info
David telah mengkaji buku gnuplot Cookbook oleh Lee Phillips
dan diterbitkan oleh Packt Publishing.

Terima kasih Izaskun dan putri saya Eider atas


kesabaran dan dukungan mereka. pequeñas os quiero.
Saya juga berterima kasih Shervin untuk memberi saya
kesempatan ini, tim OpenCV untuk pekerjaan mereka,
dukungan dari Artres, dan bantuan yang berguna yang
disediakan oleh Augmate.

Khvedchenia Ievgen adalah seorang ahli komputer visi dari Ukraina. Ia


memulai karir dengan penelitian dan pengembangan kamera berbasis sistem
bantuan driver untuk Harman International. Dia kemudian mulai bekerja sebagai
Konsultan Computer Vision untuk ESG. Saat ini, ia adalah pengembang wiraswasta
berfokus pada pengembangan aplikasi augmented reality. Ievgen adalah penulis
blog Computer Vision Pembicaraan(http://computer-vision-talks.com). di mana
ia menerbitkan artikel penelitian dan tutorial yang berkaitan dengan visi komputer
dan augmented reality.

Saya ingin mengucapkan terima kasih kepada ayah saya yang


mengilhami saya untuk belajar pemrograman ketika saya masih
14. pertolongan-Nya tidak dapat dilebih-lebihkan. Dan terima
kasih kepada ibu saya, yang selalu mendukung saya dalam
semua usaha saya. Anda selalu memberi saya kebebasan untuk
memilih cara saya sendiri dalam kehidupan ini. Terima kasih,
orang tua!
Berkat Kate, seorang wanita yang benar-benar mengubah hidup
saya dan membuatnya sangat penuh. Saya senang kita bersama-
sama. Cinta kamu.
www.it-ebooks.info
Naureen Mahmood adalah lulusan dari departemen Visualisasi di Texas A &
M University. Dia memiliki pengalaman bekerja di berbagai lingkungan
pemrograman, perangkat lunak animasi, dan mikrokontroler elektronik.
Karyanya melibatkan menciptakan aplikasi interaktif menggunakan sensor
berbasis elektronik dan rekayasa perangkat lunak. Dia juga bekerja untuk
menciptakan simulasi fisika berbasis dan penggunaannya dalam efek khusus
untuk animasi.

Saya ingin terutama menyebutkan upaya siswa lain dari Texas A


& M, yang namanya Anda pasti akan datang di dalam kode
termasuk untuk buku ini. Cairan Dinding dikembangkan sebagai
bagian dari proyek siswa dengan Austin Hines dan saya sendiri.
kredit utama untuk proyek tersebut masuk ke Austin, karena ia
adalah pikiran kreatif di balik itu. Ia juga bertanggung jawab
untuk pekerjaan yang sulit menerapkan kode simulasi cairan ke
aplikasi kita. Namun, ia tidak dapat berpartisipasi dalam menulis
buku ini karena sejumlah kesibukannya dengan pekerjaan dan
studi terkait.

Jason Saragih menerima gelar B. Eng di mekatronik (dengan pujian) dan Ph.D.
dalam ilmu komputer dari Universitas Nasional Australia, Canberra, Australia,
pada tahun 2004 dan 2008, masing-masing. Dari 2008 sampai 2010 ia adalah sesama
Postdoctoral di Robotika Institut Carnegie Mellon University, Pittsburgh, PA. Dari
2010-2012 ia bekerja di Ilmiah dan Industri Organisasi Riset Commonwealth
(CSIRO) sebagai Scientist Research. Dia saat ini menjadi Senior Research Scientist
di Fitur Visual, sebuah perusahaan startup teknologi Australia.
Dr Saragih telah membuat sejumlah kontribusi untuk bidang visi komputer,
khususnya pada topik terdeformasi pendaftaran Model dan pemodelan. Dia
adalah penulis dari dua non-profit perpustakaan open source yang banyak
digunakan dalam komunitas ilmiah; DeMoLib dan FaceTracker, yang keduanya
memanfaatkan perpustakaan visi komputer generik termasuk OpenCV.
www.it-ebooks.info
Roy Shilkrot adalah peneliti dan profesional di bidang visi komputer dan
komputer grafis. Dia memperoleh B.Sc. Ilmu Komputer dari Tel-Aviv-Yaffo
Akademik College, dan M.Sc. dari Tel-Aviv University. Saat ini ia merupakan
kandidat PhD di Media Laboratorium Massachusetts Institute of Technology
(MIT) di Cambridge.
Roy memiliki lebih dari tujuh tahun pengalaman sebagai Software Engineer di
perusahaan start-up dan perusahaan. Sebelum bergabung dengan MIT Media Lab
sebagai Asisten Penelitian ia bekerja sebagai Strategist Teknologi di Laboratorium
Inovasi Comverse, penyedia solusi telekomunikasi. Dia juga mencoba-coba
konsultasi, dan bekerja sebagai magang untuk penelitian Microsoft di Redmond.

Terima kasih kepada istri saya untuk dukungannya terbatas dan


kesabaran, masa lalu saya dan penasehat hadir di kedua akademisi dan
industri untuk kebijaksanaan mereka, dan teman-teman saya dan
rekan-rekan untuk pikiran menantang mereka.
www.it-ebooks.info
Tentang Reviewer

Kirill Kornyakov adalah Project Manager di Itseez, di mana dia memimpin


pengembangan dari OpenCV perpustakaan untuk perangkat mobile Android. Dia
mengelola kegiatan untuk pengembangan aplikasi dukungan dan komputer visi
sistem operasi mobile, termasuk optimalisasi kinerja untuk platform Tegra NVIDIA.
Sebelumnya ia bekerja di Itseez pada real-time sistem visi komputer untuk open
source dan produk komersial, kepala di antara mereka menjadi visi stereo pada GPU
dan deteksi wajah dalam lingkungan yang kompleks. Kirill memiliki B.Sc. sebuah
dan M.Sc. dari Nizhniy Novgorod State University, Rusia.

Saya ingin berterima kasih kepada keluarga saya atas dukungan


mereka, rekan-rekan saya dari Itseez, dan Nizhniy Novgorod State
University untuk diskusi yang produktif.

Luis Díaz Más menganggap dirinya visi komputer peneliti dan bergairah tentang
open source dan open-hardware masyarakat. Dia telah bekerja dengan gambar
pengolahan dan visi komputer algoritma sejak tahun 2008 dan saat ini sedang menyelesaikan
PhD
pada rekonstruksi 3D dan pengakuan tindakan. Saat ini ia bekerja di CATEC
(http://www.catec.com.es/en), Sebuah pusat penelitian untuk teknologi kedirgantaraan maju,
di mana ia terutama berkaitan dengan sistem sensoris UAV. Dia telah berpartisipasi dalam
beberapa proyek nasional dan internasional di mana ia telah membuktikan keahliannya dalam C
/ C ++
pemrograman, pengembangan aplikasi untuk sistem tertanam dengan Qt perpustakaan, dan nya
pengalaman dengan konfigurasi distribusi GNU / Linux untuk sistem embedded. Belakangan ini
ia memfokuskan minatnya di ARM
dan pengembangan CUDA.
www.it-ebooks.info
Sebastian Montabone adalah Insinyur Komputer dengan gelar Master of
Science dalam visi komputer. Dia adalah penulis artikel ilmiah yang berkaitan
dengan pengolahan gambar dan juga telah menulis sebuah buku, Awal Digital
Image Processing: Menggunakan Tools Gratis untuk Fotografer.
embedded system juga telah menarik bagi dia, khususnya ponsel. Dia
menciptakan dan mengajar kursus tentang pengembangan aplikasi untuk
ponsel, dan telah diakui sebagai juara pengembang Nokia.
Saat ini ia adalah Konsultan Software dan Pengusaha. Anda dapat mengunjungi
blog-nya diwww.samontab.com. dimana ia berbagi proyek saat ini dengan dunia.

www.it-ebooks.info
www.PacktPub.com

Mendukung file, eBook, penawaran diskon dan lebih


Anda mungkin ingin mengunjungi www.PacktPub.com untuk file dukungan
dan download yang berkaitan dengan buku Anda.
Apakah Anda tahu bahwa Packt menawarkan versi e-book dari setiap buku yang
diterbitkan, dengan PDF dan file ePub tersedia? Anda dapat meng-upgrade ke
versi e-book diwww.PacktPub. com dan sebagai pelanggan buku cetak, Anda
berhak untuk diskon pada eBook salinan. Dapatkan berhubungan dengan kami
diservice@packtpub.com untuk lebih jelasnya.
Di www.PacktPub.com. Anda juga dapat membaca koleksi artikel teknis gratis,
mendaftar untuk berbagai newsletter gratis dan menerima diskon eksklusif dan
menawarkan pada buku Packt dan eBook.

http://PacktLib.PacktPub.com

Apakah Anda perlu solusi instan untuk pertanyaan TI Anda? PacktLib online
buku perpustakaan digital Packt. Di sini, Anda dapat mengakses, membaca
dan mencari di seluruh perpustakaan Packt buku.

Mengapa Langganan?
• Sepenuhnya dicari di setiap buku yang diterbitkan oleh Packt
• Copy dan paste, cetak dan bookmark konten
• Pada permintaan dan diakses melalui browser web

Akses Gratis untuk pemegang rekening Packt


Jika Anda memiliki account dengan Packt di www.PacktPub.com. Anda dapat
menggunakan ini untuk mengakses PacktLib hari ini dan melihat sembilan buku
sepenuhnya bebas. Cukup gunakan kredensial login Anda untuk akses langsung.
www.it-ebooks.info
Daftar Isi
Kata pengantar 1
Bab 1: Cartoonifier dan Changer Kulit untuk Android 7
Mengakses webcam 9
Main pengolahan kamera loop untuk aplikasi desktop 10
Menghasilkan sketsa hitam-putih 11
Menghasilkan lukisan warna dan kartun 12
Menghasilkan sebuah "jahat" modus menggunakan ujung filter 14
Menghasilkan mode "alien" menggunakan deteksi kulit 16
algoritma kulit-deteksi 16
Menunjukkan pengguna di mana harus menempatkan wajah mereka 17
Pelaksanaan changer warna kulit 19
Porting dari desktop ke Android 24
Menyiapkan sebuah proyek Android yang menggunakan OpenCV 24
format warna yang digunakan untuk pemrosesan gambar pada Android 25
format warna masukan dari kamera 25
format warna output untuk tampilan 26
Menambahkan kode cartoonifier ke aplikasi Android NDK 28
Meninjau aplikasi Android 30
Cartoonifying gambar saat pengguna mengetuk layar 31
Menyimpan gambar ke file dan galeri gambar Android 33
Menampilkan pesan pemberitahuan Android tentang gambar yang disimpan 36
Mengubah mode kartun melalui menu bar Android 37
Mengurangi acak pepper noise dari gambar sketsa 40
Menampilkan FPS aplikasi 43
Menggunakan resolusi kamera yang berbeda 43
Menyesuaikan aplikasi 44
Ringkasan 45
www.it-ebooks.info
Daftar Isi

Bab 2: Augmented Reality Marker berbasis pada iPhone atau iPad 47


Membuat proyek iOS yang menggunakan OpenCV 48
Menambahkan kerangka OpenCV 49
Termasuk header OpenCV 51
arsitektur aplikasi 52
deteksi penanda 62
identifikasi penanda 64
konversi grayscale 64
gambar binarization 65
deteksi kontur 66
calon mencari 67
Pengakuan kode penanda 72
Membaca kode penanda 72
Penanda lokasi perbaikan 74
Menempatkan penanda dalam 3D 76
kalibrasi kamera 76
Penanda menimbulkan estimasi 78
Rendering objek virtual 3D 82
Menciptakan OpenGL lapisan render 82
Rendering adegan AR 85
Ringkasan 92
Referensi 92
Bab 3: Marker-kurang Augmented Reality 93
Marker berbasis dibandingkan penanda-kurang AR 94
Menggunakan deskriptor fitur untuk menemukan gambar yang sewenang-
wenang pada video 95
ekstraksi fitur 95
Definisi dari objek pola 98
Pencocokan poin fitur 98
PatternDetector.cpp 99
penghapusan outlier 100
Filter Cross-pertandingan 101
tes rasio 101
estimasi Homography 102
Homography perbaikan 104
Menempatkan itu semua bersama-sama 107
Pola menimbulkan estimasi 108
PatternDetector.cpp 108
Mendapatkan matriks kamera-intrinsik 110
Pattern.cpp 113
infrastruktur aplikasi 114
ARPipeline.hpp 115
ARPipeline.cpp 115
Mengaktifkan dukungan untuk visualisasi 3D di OpenCV 116
[ ii ]
www.it-ebooks.info
Daftar Isi

Membuat OpenGL jendela menggunakan OpenCV 118


Video capture menggunakan OpenCV 118
Rendering augmented reality 119
ARDrawingContext.hpp 119
ARDrawingContext.cpp 120
Demonstrasi 122
main.cpp 123
Ringkasan 126
Referensi 127
Bab 4: Menjelajahi Struktur dari Gerak Menggunakan OpenCV 129
Struktur dari konsep Gerak 130
Memperkirakan gerak kamera dari sepasang gambar 132
Titik pencocokan menggunakan deskriptor fitur yang kaya 132
Titik pencocokan menggunakan aliran optik 134
Menemukan matriks kamera 139
Merekonstruksi adegan 143
Rekonstruksi dari banyak dilihat 147
Perbaikan rekonstruksi 151
Memvisualisasikan awan titik 3D dengan PCL 155
Menggunakan kode contoh 158
Ringkasan 159
Referensi 160
Bab 5: Plat Nomor Pengakuan Menggunakan SVM dan
Jaringan saraf 161
Pengantar ANPR 161
algoritma ANPR 163
deteksi plat 166
segmentasi 167
Klasifikasi 173
pengakuan plat 176
OCR segmentasi 177
ekstraksi fitur 178
klasifikasi OCR 181
Evaluasi 185
Ringkasan 188
Bab 6: Non-kaku Pelacakan Wajah 189
Ikhtisar 191
keperluan 191
desain berorientasi 191

[ aku aku aku ]


www.it-ebooks.info
Daftar Isi

pengumpulan data: Foto dan video penjelasan 193


jenis pelatihan Data 194
alat anotasi 198
Pre-dijelaskan data (The muct dataset) 198
kendala geometris 199
analisis Procrustes 202
model bentuk linear 205
Sebuah gabungan perwakilan lokal-global yang 207
Pelatihan dan visualisasi 209
detektor fitur wajah 212
model Patch berbasis korelasi 214
Belajar model patch yang diskriminatif 214
Generatif dibandingkan model patch yang diskriminatif 218
Akuntansi untuk transformasi geometris global yang 219
Pelatihan dan visualisasi 222
deteksi wajah dan inisialisasi 224
pelacakan wajah 228
pelaksanaan wajah tracker 229
Pelatihan dan visualisasi 231
Generik dibandingkan model orang-tertentu 232
Ringkasan 233
Referensi 233
Bab 7: 3D Kepala Pose Estimasi Menggunakan AAM dan
menempatkan 235
Sekilas aktif Penampilan Model 236
Model Bentuk aktif 238
Mendapatkan nuansa PCA 240
Triangulasi 245
Segitiga tekstur warping 247
Model Instansiasi - bermain dengan Model Penampilan Aktif 249
pencarian AAM dan pas 250
MENEMPATKAN 253
Menyelam ke Posit 253
Posit dan kepala Model 256
Pelacakan dari webcam atau file video 257
Ringkasan 259
Referensi 260
Bab 8: Face Recognition menggunakan Eigenfaces atau fisherface 261
Pengantar pengenalan wajah dan deteksi wajah 261
Langkah 1: Deteksi wajah 263
Menerapkan deteksi wajah menggunakan OpenCV 264
Loading Haar atau LBP detektor untuk objek atau deteksi wajah 265
Mengakses webcam 266

[ iv ]
www.it-ebooks.info
Daftar Isi

Mendeteksi obyek menggunakan Haar atau LBP Classifier 266


Mendeteksi wajah 268
Langkah 2: Wajah preprocessing 270
deteksi mata 271
daerah pencarian mata 272
Langkah 3: Mengumpulkan wajah dan belajar dari mereka 281
Mengumpulkan wajah preprocessed untuk pelatihan 283
Pelatihan sistem pengenalan wajah dari wajah yang dikumpulkan 285
Melihat pengetahuan yang dipelajari 287
rata-rata wajah 289
Nilai Eigen, Eigenfaces, dan fisherface 290
Langkah 4: pengenalan wajah 292
Wajah identifikasi: Mengakui orang dari wajah mereka 292
verifikasi wajah: Memvalidasi bahwa itu adalah orang yang diklaim 292
Sentuhan: Menyimpan dan loading file 295
Sentuhan: Membuat GUI yang bagus dan interaktif 295
Menggambar elemen GUI 297
Memeriksa dan penanganan klik mouse 306
Ringkasan 308
Referensi 309
Indeks 311

[v]
www.it-ebooks.info
www.it-ebooks.info
Kata pengantar
Menguasai OpenCV dengan Proyek Visi Komputer Praktis berisi sembilan bab, dimana
setiap bab adalah tutorial untuk seluruh proyek dari awal sampai akhir, berdasarkan
antarmuka C ++ OpenCV termasuk kode sumber penuh. Penulis masing-masing bab
dipilih untuk kontribusi online mereka dianggap baik untuk masyarakat OpenCV pada
topik itu, dan buku itu ditinjau oleh salah satu pengembang OpenCV utama. Daripada
menjelaskan dasar-dasar fungsi OpenCV, ini adalah buku pertama yang menunjukkan
bagaimana
untuk menerapkan OpenCV untuk memecahkan seluruh masalah, termasuk
beberapa proyek 3D kamera (augmented reality, Struktur 3D dari Gerak, interaksi
Kinect) dan beberapa proyek analisis wajah (seperti, deteksi kulit, wajah yang
sederhana dan deteksi mata, kompleks wajah fitur pelacakan, kepala 3D estimasi
orientasi, dan pengenalan wajah), oleh karena itu membuat pendamping yang
bagus untuk buku OpenCV yang ada.

Apa buku ini mencakup


Bab 1, Cartoonifier dan Changer Kulit untuk Android, berisi tutorial dan kode
sumber lengkap untuk kedua aplikasi desktop dan aplikasi Android yang secara
otomatis menghasilkan kartun atau lukisan dari gambar kamera nyata, dengan
beberapa kemungkinan jenis kartun termasuk changer warna kulit.
Bab 2, Berbasis Marker Augmented Reality pada iPhone atau iPad, berisi
tutorial lengkap tentang cara membangun sebuah aplikasi berbasis marker
augmented reality (AR) untuk iPad dan perangkat iPhone dengan penjelasan
tentang setiap langkah dan kode sumber.
bagian 3, Marker-kurang Augmented Reality, berisi tutorial lengkap tentang
bagaimana mengembangkan aplikasi reality desktop yang penanda-kurang
augmented dengan penjelasan tentang apa penanda-kurang AR adalah dan kode
sumber.
Bab 4, Menjelajahi Struktur dari Gerak Menggunakan OpenCV, berisi pengenalan
Struktur dari Motion (SFM) melalui penerapan konsep SFM di OpenCV. pembaca
akan belajar bagaimana untuk merekonstruksi geometri 3D dari beberapa gambar
2D dan posisi kamera perkiraan.
www.it-ebooks.info
Kata pengantar

Bab 5, Plat Nomor Pengakuan Menggunakan SVM dan Neural Networks,


berisi tutorial dan kode sumber lengkap untuk membangun aplikasi
pengenalan plat nomor otomatis menggunakan algoritma pengenalan pola
menggunakan mesin dukungan vektor dan Jaringan Syaraf Tiruan. pembaca
akan belajar bagaimana untuk melatih dan memprediksi algoritma
pengenalan pola untuk memutuskan apakah gambar adalah plat nomor atau
tidak. Ini juga akan membantu mengklasifikasikan serangkaian fitur menjadi
karakter.
Bab 6, Non-kaku Pelacakan Wajah, berisi tutorial dan kode sumber lengkap
untuk membangun sistem pelacakan wajah dinamis yang dapat model dan
melacak banyak bagian kompleks wajah seseorang.
Bab 7, 3D Kepala Pose Estimasi Menggunakan AAM dan Posit, berisi semua latar
belakang yang diperlukan untuk memahami apa Aktif Penampilan Model (AAMs)
dan bagaimana membuat mereka dengan OpenCV menggunakan satu set frame
wajah dengan ekspresi wajah yang berbeda. Selain itu, bab ini menjelaskan
bagaimana untuk mencocokkan frame yang diberikan melalui kemampuan pas
ditawarkan oleh AAMs. Kemudian, dengan menerapkan algoritma Posit, satu
dapat menemukan kepala 3D berpose.
Bab 8, Face Recognition menggunakan Eigenfaces atau fisherface, berisi tutorial
lengkap dan kode sumber untuk aplikasi real-time wajah-pengakuan yang
mencakup wajah dasar dan deteksi mata untuk menangani rotasi wajah dan
kondisi pencahayaan yang berbeda-beda dalam gambar.
Bab 9, Mengembangkan Dinding Fluid Menggunakan Microsoft Kinect,
meliputi pengembangan lengkap simulasi cairan interaktif disebut Cairan Wall,
yang menggunakan sensor Kinect. Bab ini akan menjelaskan bagaimana
menggunakan data Kinect dengan metode aliran optik OpenCV dan
mengintegrasikannya ke dalam pemecah cairan.
Anda dapat men-download bab ini dari:
http://www.packtpub.com/sites/default/ file / download /
7829OS_Chapter9_Developing_Fluid_Wall_Using_the_
Microsoft_Kinect.pdf.

Apa yang Anda butuhkan untuk buku ini


Anda tidak perlu memiliki pengetahuan khusus dalam visi komputer untuk
membaca buku ini, tetapi Anda harus memiliki baik C C keterampilan / ++
pemrograman dan pengalaman dasar dengan OpenCV sebelum membaca buku ini.
Pembaca tanpa pengalaman dalam OpenCV mungkin ingin membaca buku Belajar
OpenCV untuk pengenalan fitur OpenCV, atau membaca OpenCV 2 Cookbook
untuk contoh tentang cara menggunakan OpenCV dengan direkomendasikan C / C
++ pola, karena Menguasai OpenCV dengan Praktis Visi Proyek Komputer akan
menunjukkan Anda bagaimana untuk memecahkan masalah nyata, dengan asumsi
Anda sudah akrab dengan dasar-dasar OpenCV dan C / C ++ pembangunan.

[2]
www.it-ebooks.info
Kata pengantar

Selain C / C ++ dan pengalaman OpenCV, Anda juga akan membutuhkan komputer,


dan IDE pilihan Anda (seperti Visual Studio, Xcode, Eclipse, atau QtCreator, berjalan
pada Windows, Mac atau Linux). Beberapa bab memiliki persyaratan lebih lanjut,
khususnya:
• Untuk mengembangkan aplikasi Android, Anda akan memerlukan sebuah perangkat Android,
pengembangan Android alat, dan dasar pengalaman pembangunan Android.
• Untuk mengembangkan aplikasi iOS, Anda akan memerlukan sebuah iPhone, iPad,
atau perangkat iPod Touch, iOS
alat pengembangan (termasuk komputer Apple, Xcode
IDE, dan Sertifikat Pengembang Apple), dan iOS dasar dan Objective-
pengalaman pengembangan C.
• Beberapa proyek desktop yang memerlukan webcam terhubung ke komputer Anda. Apa
saja umum USB webcam harus cukup, tetapi webcam minimal 1 megapiksel mungkin
diinginkan.
• CMake digunakan dalam beberapa proyek, termasuk OpenCV itu sendiri, untuk
membangun seluruh operasi
sistem dan kompiler. Sebuah pemahaman dasar tentang sistem build diperlukan, dan pengetahuan
tentang cross-platform bangunan dianjurkan.
• Pemahaman tentang aljabar linier diharapkan, seperti vektor dasar dan matriks operasi dan
dekomposisi eigen.

Siapa buku ini adalah untuk


Menguasai OpenCV dengan Proyek Visi Komputer Praktis adalah buku yang sempurna
untuk pengembang dengan pengetahuan OpenCV dasar untuk membuat proyek
visi komputer praktis, serta untuk ahli OpenCV berpengalaman yang ingin
menambahkan lebih topik visi komputer untuk keahlian mereka. Hal ini ditujukan
untuk siswa senior yang ilmu komputer universitas, lulusan, peneliti, dan ahli visi
komputer yang ingin memecahkan masalah nyata menggunakan OpenCV C ++
antarmuka, melalui praktis langkah-demi-langkah tutorial.

konvensi
Dalam buku ini, Anda akan menemukan sejumlah gaya teks yang
membedakan antara berbagai jenis informasi. Berikut adalah beberapa
contoh dari gaya ini, dan penjelasan tentang makna mereka.
kata kode dalam teks yang ditampilkan sebagai berikut: "Anda harus
menempatkan sebagian besar kode bab ini ke dalam cartoonifyImage ()
fungsi."

[3]
www.it-ebooks.info
Kata pengantar

Sebuah blok kode diatur sebagai berikut:


int cameraNumber = 0;
if (argc> 1)
cameraNumber = atoi (argv [1]);
Dapatkan akses ke kamera. cv :: VideoCapture capture;

Ketika kita ingin menarik perhatian Anda ke bagian tertentu dari sebuah
blok kode, garis-garis yang relevan atau barang diatur dalam huruf
tebal:
Dapatkan akses ke kamera. cv :: VideoCapture capture; camera.open
(cameraNumber); if (! camera.isOpened ()) {
std :: cerr << "ERROR: Tidak dapat mengakses kamera atau video!" <<

istilah baru dan kata-kata penting yang ditampilkan dalam huruf tebal. Kata-
kata yang Anda lihat di layar, di menu atau kotak dialog misalnya, muncul
dalam teks seperti ini: "mengklik tombol Next bergerak Anda ke layar
berikutnya".

Peringatan atau catatan penting muncul dalam sebuah kotak seperti ini.

Tips dan trik muncul seperti ini.

umpan balik pembaca


Umpan balik dari pembaca kami selalu diterima. Marilah kita tahu apa yang Anda
pikirkan tentang buku-apa yang Anda suka atau mungkin tidak menyukai. umpan
balik pembaca penting bagi kita untuk mengembangkan judul yang Anda benar-
benar mendapatkan hasil maksimal dari.
Untuk mengirimkan umpan balik umum, cukup kirim e-mail ke
feedback@packtpub.com, Dan menyebutkan judul buku melalui subjek pesan
Anda.
Jika ada topik yang Anda memiliki keahlian dalam dan Anda tertarik baik tertulis
atau berkontribusi buku, lihat panduan penulis kami di
www.packtpub.com/authors.

[4]
www.it-ebooks.info
Kata pengantar

dukungan pelanggan
Sekarang bahwa Anda adalah pemilik bangga sebuah buku Packt, kami memiliki
sejumlah hal untuk membantu Anda untuk mendapatkan hasil maksimal dari
pembelian Anda.

Download contoh kode


Anda dapat men-download file contoh kode untuk semua buku Packt Anda
telah membeli dari akun di http://www.PacktPub.com. Jika Anda membeli
buku ini di tempat lain, Anda dapat mengunjungi
http://www.PacktPub.com/support dan mendaftar untuk memiliki e-mail
langsung kepada Anda file.

ralat
Meskipun kami telah mengambil setiap perawatan untuk memastikan keakuratan dari
konten kami, kesalahan bisa terjadi. Jika Anda menemukan kesalahan di salah satu
buku-mungkin kesalahan dalam teks atau kode-kami akan berterima kasih jika Anda
akan melaporkan ini kepada kami. Dengan demikian, Anda dapat menyimpan pembaca
lainnya dari frustrasi dan membantu kami meningkatkan versi berikutnya dari buku ini.
Jika Anda menemukan ralat, silahkan melaporkannya dengan mengunjungi http:
//www.packtpub. com / support, Memilih buku Anda, klik pada formulir pengajuan
ralat Link, dan memasuki rincian ralat Anda. Setelah ralat Anda diverifikasi, kiriman Anda
akan diterima dan ralat yang akan di-upload di website kami, atau ditambahkan ke daftar
ralat yang ada, di bawah bagian Errata dari gelar itu. Setiap ralat yang ada dapat dilihat
dengan memilih judul darihttp://www.packtpub.com/support.

Pembajakan
Pembajakan materi hak cipta di Internet adalah masalah yang sedang berlangsung
di semua media. Pada Packt, kita mengambil perlindungan hak cipta dan lisensi
kami sangat serius. Jika Anda datang di setiap salinan ilegal dari karya-karya kami,
dalam bentuk apapun, di internet, silakan berikan kami dengan alamat lokasi atau
nama website segera sehingga kita bisa mengejar obat.
Silahkan hubungi kami di copyright@packtpub.com dengan
link ke materi bajakan yang dicurigai.
Kami menghargai bantuan Anda dalam melindungi penulis kami, dan
kemampuan kita untuk membawa Anda konten yang berharga.

pertanyaan
Anda dapat menghubungi kami di questions@packtpub.com jika Anda
mengalami masalah dengan segala aspek dari buku, dan kami akan melakukan
yang terbaik untuk mengatasinya.
[5]
www.it-ebooks.info
www.it-ebooks.info
Cartoonifier dan Kulit
Changer untuk
Android
Bab ini akan menunjukkan cara untuk menulis beberapa gambar pemrosesan data
filter untuk smartphone Android dan tablet, tertulis pertama untuk desktop (di C /
C ++) dan kemudian porting ke Android (dengan sama C / C ++ kode tetapi
dengan GUI Java), karena ini adalah skenario direkomendasikan ketika
mengembangkan untuk perangkat mobile. Bab ini akan mencakup:
• Bagaimana mengkonversi gambar kehidupan nyata untuk gambar sketsa
• Bagaimana mengkonversi ke sebuah lukisan dan overlay sketsa untuk menghasilkan
kartun
• Sebuah "jahat" mode menakutkan untuk membuat karakter buruk
bukan karakter yang baik
• Sebuah detektor dasar kulit dan warna changer kulit, untuk memberikan seseorang hijau
"alien" kulit
• Bagaimana mengkonversi proyek dari aplikasi desktop ke aplikasi seluler

Screenshot berikut menunjukkan aplikasi akhir Cartoonifier berjalan pada


tablet android:
www.it-ebooks.info
Cartoonifier dan Kulit Changer untuk Android

Kami ingin membuat frame kamera dunia nyata terlihat seperti mereka benar-
benar dari kartun. Ide dasarnya adalah untuk mengisi bagian datar dengan
beberapa warna dan kemudian menggambar garis tebal di tepi kuat. Dengan kata
lain, daerah datar harus menjadi jauh lebih datar dan ujung-ujungnya harus
menjadi jauh lebih jelas. Kami akan mendeteksi tepi dan menghaluskan daerah
datar, kemudian menarik tepi ditingkatkan kembali di atas untuk menghasilkan
kartun atau efek buku komik.
Ketika mengembangkan aplikasi visi komputer mobile, itu adalah ide yang baik
untuk membangun sebuah versi desktop sepenuhnya bekerja terlebih dahulu
sebelum porting ke ponsel, karena jauh lebih mudah untuk mengembangkan dan
men-debug program desktop dari aplikasi mobile! Bab ini karena itu akan dimulai
dengan program desktop Cartoonifier lengkap yang dapat Anda buat menggunakan
IDE favorit Anda (misalnya, Visual Studio, Xcode, Eclipse, QtCreator, dan
sebagainya). Setelah itu bekerja dengan baik pada desktop, bagian terakhir
menunjukkan bagaimana untuk port ke Android (atau berpotensi iOS) dengan
Eclipse. Karena kita akan membuat dua proyek yang berbeda yang sebagian besar
berbagi kode sumber yang sama dengan antarmuka pengguna grafis yang berbeda,
Anda bisa membuat perpustakaan yang dihubungkan oleh kedua proyek, tetapi
untuk kesederhanaan kita akan menempatkan desktop dan proyek Android
samping satu sama lain,cartoon.cpp dan cartoon.h, Yang berisi semua kode
pengolahan gambar) dari Desktopmap. Sebagai contoh:
• C: \ Cartoonifier_Desktop \ cartoon.cpp
• C: \ Cartoonifier_Desktop \ cartoon.h
• C: \ Cartoonifier_Desktop \ main_desktop.cpp
• C: \ Cartoonifier_Android \ ...

Aplikasi desktop menggunakan jendela OpenCV GUI, menginisialisasi kamera,


dan dengan setiap kamera bingkai menyebut cartoonifyImage ()Fungsi yang
berisi sebagian besar kode dalam bab ini. Ini kemudian menampilkan gambar
diproses pada jendela GUI.
Demikian pula, aplikasi Android menggunakan jendela Android GUI,
menginisialisasi kamera menggunakan Java, dan dengan setiap frame kamera
panggilan yang sama persis C ++ cartoonifyImage ()fungsi seperti yang disebutkan
sebelumnya, tetapi dengan menu Android dan masukan jari-touch. Bab ini akan
menjelaskan bagaimana membuat aplikasi desktop dari awal, dan aplikasi Android
dari salah satu proyek sampel OpenCV Android. Jadi, pertama Anda harus membuat
program desktop dalam IDE favorit Anda, denganmain_desktop.cpp mengajukan
untuk memegang kode GUI yang diberikan dalam bagian berikut, seperti loop utama,
fungsi webcam, dan input keyboard, dan Anda harus membuat cartoon.cppfile yang
akan dibagi antara proyek. Anda harus menempatkan sebagian besar kode bab ini
menjadi
cartoon.cpp sebagai fungsi yang disebut cartoonifyImage ().

[8]
www.it-ebooks.info
Bab 1

Mengakses webcam
Untuk mengakses perangkat webcam atau kamera komputer, Anda hanya dapat
memanggil Buka() pada suatu cv :: VideoCapture objek (metode OpenCV
mengakses perangkat kamera Anda), dan lulus 0sebagai nomor ID kamera
default. Beberapa komputer telah beberapa kamera terpasang atau mereka tidak
bekerja sebagai standar kamera0; sehingga praktek umum untuk memungkinkan
pengguna untuk lulus nomor kamera yang diinginkan sebagai argumen baris
perintah, dalam kasus mereka ingin mencoba kamera 1, 2, atau -1, misalnya. Kami
juga akan mencoba untuk mengatur resolusi kamera 640 x 480 menggunakancv
:: VideoCapture :: set (), Dalam rangka untuk menjalankan lebih cepat pada
kamera resolusi tinggi.

Tergantung pada model kamera, driver, atau sistem Anda, OpenCV


mungkin tidak mengubah sifat kamera Anda. Hal ini tidak penting
untuk proyek ini, jadi jangan khawatir jika tidak bekerja dengan
kamera Anda.

Anda dapat menempatkan kode ini di utama() fungsi Anda main_desktop.cpp:


int cameraNumber = 0;
if (argc> 1)
cameraNumber = atoi (argv [1]);

Dapatkan akses ke kamera. Kamera cv :: VideoCapture; camera.open


(cameraNumber); if (! camera.isOpened ()) {
std :: cerr << "ERROR: Tidak dapat mengakses kamera atau
video!" << std :: endl;
exit (1);
}

Cobalah untuk mengatur resolusi kamera.


camera.set (cv :: CV_CAP_PROP_FRAME_WIDTH,
640); camera.set (cv ::
CV_CAP_PROP_FRAME_HEIGHT, 480);

Setelah webcam telah diinisialisasi, Anda bisa ambil gambar kamera saat ini
sebagai cv :: Matobjek (OpenCV kontainer gambar). Anda bisa ambil setiap
frame kamera dengan menggunakan C ++ Operator streaming dari Andacv
:: VideoCapture keberatan ke cv :: Mat keberatan, sama seperti jika Anda
mendapatkan masukan dari konsol.

[9]
www.it-ebooks.info
Cartoonifier dan Kulit Changer untuk Android

OpenCV membuatnya sangat mudah untuk memuat file video (seperti AVI
atau MPG file) dan menggunakannya bukan webcam. Satu-satunya
perbedaan kode Anda akan bahwa Anda harus membuatcv ::
VideoCapture keberatan dengan nama file video, seperti camera.open
( "my_video.avi"), Bukan jumlah kamera, seperti camera.open (0).
Kedua metode membuatcv :: VideoCapture objek yang dapat
digunakan dengan cara yang sama.

Main pengolahan kamera loop


untuk aplikasi desktop
Jika Anda ingin menampilkan jendela GUI pada layar menggunakan OpenCV,
Anda menelepon cv :: imshow () untuk setiap gambar, tetapi Anda juga harus
memanggil cv :: waitKey () sekali per bingkai, jika jendela Anda tidak akan
memperbarui sama sekali! Panggilancv :: waitKey (0) menunggu tanpa batas
waktu sampai pengguna menekan tombol di jendela, namun angka positif seperti
waitKey (20) atau lebih tinggi akan menunggu setidaknya bahwa banyak
milidetik.

Masukan loop utama ini di main_desktop.cpp, Sebagai dasar untuk kamera aplikasi real-time Anda:

sementara (benar) {
Ambil frame kamera depan. cv :: Mat cameraFrame;
Kamera >> cameraFrame;
jika (cameraFrame.empty ()) {
std :: cerr << "ERROR: Bisa tidak ambil bingkai kamera."
<< std :: endl;
exit (1);
}
Buat kosong output gambar, bahwa kita akan menarik ke. cv :: Mat
displayedFrame (cameraFrame.size (), cv :: CV_8UC3);

Jalankan filter cartoonifier pada frame kamera.


cartoonifyImage (cameraFrame, displayedFrame);

Menampilkan gambar diproses ke layar. imshow ( "Cartoonifier",


displayedFrame);

PENTING: Tunggu setidaknya 20 milidetik,


sehingga gambar dapat ditampilkan pada layar!
Juga memeriksa apakah tombol ditekan di jendela GUI.
Perhatikan bahwa itu harus menjadi "char" untuk mendukung Linux.
Char menekan tombol = cv :: // Perlu ini untuk melihat apa-apa!
waitKey (20);
jika (tombol ditekan // Luput Key
== 27) {
[ 10 ]
www.it-ebooks.info
Bab 1

Keluar dari program! istirahat;


}
} // akhir sementara

Menghasilkan sketsa hitam-putih


Untuk mendapatkan sketsa (gambar hitam-putih) dari frame kamera, kita
akan menggunakan filter tepi-deteksi; sedangkan untuk mendapatkan
lukisan warna, kita akan menggunakan filter tepi-melestarikan (filter
bilateral) untuk lebih memperlancar daerah datar sambil menjaga tepi utuh.
Dengan overlay gambar sketsa di atas lukisan warna, kita memperoleh efek
kartun seperti yang ditunjukkan sebelumnya dalam screenshot dari aplikasi
akhir.
Ada banyak filter deteksi tepi yang berbeda, seperti Sobel, Scharr, filter Laplacian,
atau detektor Canny-tepi. Kami akan menggunakan Laplacian penyaring tepi
karena menghasilkan tepi yang terlihat paling mirip dengan sketsa tangan
dibandingkan dengan Sobel atau Scharr, dan yang cukup konsisten dibandingkan
dengan detektor Canny-tepi, yang menghasilkan gambar garis sangat bersih tetapi
lebih dipengaruhi oleh gangguan acak dalam frame kamera dan gambar garis
karena itu sering berubah drastis antara frame.
Namun demikian, kita masih perlu untuk mengurangi kebisingan di gambar sebelum
kita menggunakan Laplacian Filter tepi. Kami akan menggunakan filter Median karena
itu baik di menghilangkan suara sementara menjaga tepi tajam; juga, itu tidak lambat
seperti filter bilateral. Sejak filter Laplacian menggunakan gambar grayscale, kita harus
mengkonversi dari default Format BGR OpenCV untuk Grayscale. Dalam file
kosongcartoon.cpp, Masukkan kode ini di bagian atas sehingga Anda dapat
mengakses OpenCV dan Standard C ++ template tanpa mengetik CV:: dan std ::
dimana mana:
Sertakan OpenCV C ++ Antarmuka #include "opencv2 / opencv.hpp"

menggunakan namespace cv;


menggunakan namespace std;

Masukan ini dan semua kode yang tersisa di cartoonifyImage ()


fungsi dalam cartoon.cpp mengajukan:
Mat abu-abu;
cvtColor (srcColor, abu-abu, CV_BGR2GRAY);
const int MEDIAN_BLUR_FILTER_SIZE = 7;
medianBlur (abu-abu, abu-abu, MEDIAN_BLUR_FILTER_SIZE);
tepi Mat;
const int LAPLACIAN_FILTER_SIZE = 5;
Laplacian (abu-abu, tepi, CV_8U, LAPLACIAN_FILTER_SIZE);

[ 11 ]
www.it-ebooks.info
Cartoonifier dan Kulit Changer untuk Android

Laplacian Filter menghasilkan tepi dengan berbagai kecerahan, sehingga untuk


membuat tepi terlihat lebih seperti sebuah sketsa kita menerapkan ambang biner
untuk membuat tepi putih atau hitam:
Mat masker;
const int EDGES_THRESHOLD = 80;
ambang batas (tepi, masker, EDGES_THRESHOLD, 255, THRESH_BINARY_INV);

Dalam gambar berikut, Anda dapat melihat gambar asli (sisi kiri) dan tepi
masker yang dihasilkan (kanan) yang terlihat mirip dengan gambar sketsa.
Setelah kami menghasilkan lukisan warna (dijelaskan kemudian), kita dapat
menempatkan tepi masker ini di atas untuk gambar garis hitam:

Menghasilkan lukisan warna dan kartun


Sebuah filter bilateral yang kuat menghaluskan daerah datar sambil menjaga tepi
tajam, dan karena itu besar sebagai cartoonifier otomatis atau filter lukisan,
kecuali bahwa itu sangat lambat (yang, diukur dalam detik atau bahkan menit
bukan milidetik!). oleh karena itu kita akan menggunakan beberapa trik untuk
mendapatkan cartoonifier baik yang masih berjalan pada kecepatan yang dapat
diterima. Trik yang paling penting yang dapat kita gunakan adalah dengan
melakukan penyaringan bilateral pada resolusi yang lebih rendah. Ini akan
memiliki efek yang sama seperti pada resolusi penuh, tapi akan berjalan lebih
cepat. Mari kita mengurangi jumlah total piksel dengan faktor empat (misalnya,
setengah lebar dan setengah tinggi):
Ukuran size = srcColor.size ();
Ukuran smallSize;
smallSize.width = size.width / 2;
smallSize.height = size.height / 2;
Mat smallImg = Mat (smallSize, CV_8UC3);
mengubah ukuran (srcColor, smallImg, smallSize, 0,0, INTER_LINEAR);

[ 12 ]
www.it-ebooks.info
Bab 1

Daripada menerapkan filter bilateral besar, kami akan menerapkan banyak filter
bilateral kecil untuk menghasilkan efek kartun yang kuat dalam waktu kurang.
Kami akan memotong filter (lihat gambar berikut) sehingga bukan melakukan
seluruh filter (misalnya, ukuran filter 21 x 21 ketika kurva lonceng adalah 21 piksel
lebar), itu hanya menggunakan ukuran filter minimum yang diperlukan untuk
hasil meyakinkan (misalnya, dengan ukuran filter hanya 9 x 9 bahkan jika kurva
lonceng adalah 21 piksel lebar). Filter dipotong ini akan menerapkan bagian
utama dari filter (wilayah abu-abu) tanpa membuang-buang waktu pada bagian
kecil dari filter (area putih di bawah kurva), sehingga akan menjalankan beberapa
kali lebih cepat:

Kami memiliki empat parameter yang mengontrol filter bilateral: kekuatan warna,
kekuatan posisi, ukuran, dan jumlah pengulangan. Kami membutuhkan Mat suhu
sejakbilateralFilter () tidak bisa menimpa input (disebut sebagai "di tempat
pengolahan"), tapi kita dapat menerapkan satu filter menyimpan Mat temp dan
filter lain menyimpan kembali ke input:
Mat tmp = Mat // kekuatan Filter warna.
(smallSize,
CV_8UC3);
// kekuatan Ruang. Mempengaruhi
int pengulangan = 7; // kecepatan. Pengulangan untuk
efek kartun yang kuat.
for (int i = 0; i <pengulangan; i ++) {
int ksize = 9; // ukuran Filter. Memiliki dampak yang besar pada
kecepatan.
ganda sigmaColor = 9;
ganda sigmaSpace = 7;
bilateralFilter (smallImg, tmp, ksize, sigmaColor,
sigmaSpace); bilateralFilter (tmp, smallImg, ksize,
sigmaColor, sigmaSpace);
}

[ 13 ]
www.it-ebooks.info
Cartoonifier dan Kulit Changer untuk Android

Ingatlah bahwa ini diaplikasikan pada gambar menyusut, jadi kita perlu
memperluas gambar kembali ke ukuran aslinya. Kemudian kita dapat overlay
topeng tepi yang kami temukan sebelumnya. Untuk overlay tepi topeng "sketsa"
ke bilateral filter "lukisan" (sisi kiri dari gambar berikut), kita bisa mulai dengan
latar belakang hitam dan menyalin "lukisan" piksel yang tidak tepi dalam
"sketsa" topeng:
Mat bigImg;
mengubah ukuran (smallImg, bigImg, ukuran, 0,0,
INTER_LINEAR); dst.setTo (0);
bigImg.copyTo (dst, masker);

Hasilnya adalah versi kartun dari foto asli, seperti yang ditunjukkan pada sisi
kanan gambar, di mana "sketsa" mask overlay pada "lukisan":

Menghasilkan sebuah "jahat"


modus menggunakan ujung
filter
Kartun dan komik selalu memiliki karakter baik dan buruk. Dengan kombinasi
yang tepat dari filter edge, gambar menakutkan dapat dihasilkan dari orang-
orang yang paling tak berdosa! Caranya adalah dengan menggunakan kecil-tepi
filter yang akan menemukan banyak tepi seluruh gambar, kemudian
menggabungkan tepi menggunakan filter Median kecil.
Kami akan melakukan ini pada gambar grayscale dengan beberapa pengurangan
kebisingan, sehingga kode sebelumnya untuk mengkonversi gambar asli ke
grayscale dan menerapkan 7 x 7 Median filter yang harus digunakan lagi (gambar
pertama pada gambar berikut menunjukkan output dari grayscale blur median).
Bukannya mengikuti dengan filter Laplacian dan ambang Binary, kita bisa
mendapatkan tampilan yang menakutkan jika kita menerapkan 3 x 3 Scharr gradien
penyaring sepanjang x dan y (gambar kedua di gambar), dan kemudian
menerapkan ambang biner dengan sangat cutoff rendah (gambar ketiga dalam
gambar) dan Median blur 3 x 3, memproduksi final "jahat" topeng (gambar keempat
pada gambar):

[ 14 ]
www.it-ebooks.info
Bab 1

Mat abu-abu;
cvtColor (srcColor, abu-abu, CV_BGR2GRAY); const
int MEDIAN_BLUR_FILTER_SIZE = 7; medianBlur
(abu-abu, abu-abu, MEDIAN_BLUR_FILTER_SIZE);
tepi tikar, edges2;
Scharr (srcGray, tepi, CV_8U, 1, 0);
Scharr (srcGray, edges2, CV_8U, 1, 0, -1);
tepi + = edges2; // Gabungkan x & y tepi bersama-sama.
const int EVIL_EDGE_THRESHOLD = 12;
ambang batas (tepi, masker, EVIL_EDGE_THRESHOLD, 255,
THRESH_BINARY_INV); medianBlur (masker, masker, 3);

Sekarang bahwa kita memiliki "jahat" topeng, kita dapat overlay masker ini ke
cartoonified "lukisan" gambar seperti yang kami lakukan dengan rutin "sketsa"
tepi masker. Hasil akhir ditampilkan di sisi kanan gambar berikut:

[ 15 ]

www.it-ebooks.info
Cartoonifier dan Kulit Changer untuk Android

Menghasilkan mode "alien"


menggunakan deteksi kulit
Sekarang bahwa kita memiliki modus sketsa, modus kartun (lukisan + topeng
sketsa), dan modus kejahatan (lukisan + topeng jahat), untuk bersenang-senang
mari kita coba sesuatu yang lebih kompleks: "asing" mode, dengan mendeteksi
daerah kulit menghadapi dan kemudian mengubah warna kulit menjadi hijau.

algoritma kulit-deteksi
Ada banyak teknik yang berbeda digunakan untuk mendeteksi daerah kulit, dari
ambang batas warna yang sederhana menggunakan RGB (Red-Green-Blue) atau HSV
(Hue-Saturation-Brightness) nilai atau histogram warna perhitungan dan proyeksi
ulang, algoritma mesin-belajar yang kompleks model campuran bahwa kamera perlu
kalibrasi dalam ruang warna CIELAB dan pelatihan secara offline dengan banyak wajah
sampel, dan sebagainya. Tetapi bahkan metode yang kompleks tidak selalu bekerja
dengan kuat di berbagai kamera dan pencahayaan kondisi dan jenis kulit. Karena kita
ingin deteksi kulit kita untuk berjalan pada perangkat mobile tanpa kalibrasi atau
pelatihan, dan kami hanya menggunakan deteksi kulit untuk "bersenang-senang" filter
gambar, itu sudah cukup bagi kita untuk menggunakan metode kulit-deteksi sederhana.
Namun, respon warna dari sensor kamera kecil di perangkat mobile cenderung
bervariasi secara signifikan,

Sebagai contoh, detektor kulit HSV sederhana dapat mengobati pixel setiap kulit
jika rona cukup merah, saturasi cukup tinggi tetapi tidak sangat tinggi, dan
kecerahan tidak terlalu gelap atau terlalu terang. Tapi kamera ponsel sering
memiliki keseimbangan putih yang buruk, dan sehingga kulit seseorang mungkin
terlihat sedikit biru bukan merah, dan seterusnya, dan ini akan menjadi masalah
besar untuk sederhana HSV thresholding.
Solusi yang lebih kuat adalah dengan melakukan deteksi wajah dengan Haar atau
LBP cascade classifier (ditampilkan dalam Bab 8, Face Recognition menggunakan
Eigenfaces), dan kemudian melihat berbagai warna untuk pixel di tengah wajah
yang terdeteksi karena Anda tahu bahwa mereka piksel harus piksel kulit orang
yang sebenarnya. Anda kemudian bisa memindai seluruh gambar atau daerah
terdekat untuk piksel dari warna yang sama sebagai pusat wajah. Hal ini memiliki
keuntungan bahwa sangat mungkin untuk menemukan setidaknya beberapa
daerah kulit yang benar dari setiap orang yang terdeteksi tidak peduli apa warna
kulit mereka atau bahkan jika kulit mereka muncul agak biru atau merah pada
gambar kamera.

[ 16 ]
www.it-ebooks.info
Bab 1

Sayangnya, deteksi wajah menggunakan pengklasifikasi cascade cukup lambat pada


perangkat mobile saat ini, jadi metode ini mungkin kurang ideal untuk beberapa
aplikasi mobile real-time. Di sisi lain, kita dapat mengambil keuntungan dari fakta
bahwa untuk aplikasi mobile dapat diasumsikan bahwa pengguna akan memegang
kamera langsung menuju wajah seseorang dari dekat, dan karena pengguna
memegang kamera di tangan mereka, yang mereka dapat dengan mudah bergerak,
itu cukup masuk akal untuk meminta pengguna untuk menempatkan wajah mereka
di lokasi tertentu dan jarak, daripada mencoba untuk mendeteksi lokasi dan ukuran
wajah mereka. Ini adalah dasar dari banyak aplikasi ponsel di mana aplikasi
meminta pengguna untuk menempatkan wajah mereka pada posisi tertentu atau
mungkin secara manual menyeret poin pada layar untuk menunjukkan di mana
sudut-sudut wajah mereka di foto. Jadi mari kita

Menunjukkan pengguna di mana harus


menempatkan wajah mereka
Ketika mode asing pertama dimulai, kita akan menarik garis wajah di atas bingkai
kamera sehingga pengguna tahu di mana untuk menempatkan wajah mereka. Kami
akan menggambar elips besar yang mencakup 70 persen dari tinggi gambar, dengan
aspek rasio tetap 0,72 sehingga wajah tidak akan menjadi terlalu kurus atau gemuk
tergantung pada rasio aspek kamera:
Menggambar wajah warna ke latar belakang hitam. Mat
faceOutline = Mat :: nol (ukuran, CV_8UC3);
warna skalar = CV_RGB (255,255,0); // Kuning.
Ketebalan int = 4;
Gunakan 70% dari tinggi layar sebagai tinggi wajah. int sw =
size.width; int sh = size.height;
int faceH = sh / 2 * 70/100; // "faceH" adalah radius elips.
Skala lebar menjadi bentuk yang sama untuk setiap lebar
layar. int faceW = faceH * 72/100;
// Menggambar garis wajah.
elips (faceOutline, Point (sw / 2, sh / 2), Size (faceW,
faceH), 0, 0, 360, warna, ketebalan, CV_AA);

Untuk membuatnya lebih jelas bahwa itu adalah wajah, mari kita juga
menggambar dua garis mata. Daripada menggambar mata sebagai elips, kita
bisa membuatnya sedikit lebih realistis (lihat gambar berikut) dengan
menggambar elips terpotong untuk bagian atas mata dan elips terpotong untuk
bagian bawah mata, karena kita dapat menentukan memulai dan mengakhiri
sudut ketika menggambar denganelips():
Menggambar garis mata, seperti 2 busur per mata. int eyeW = faceW *
23/100;int eyeH = faceH * 11/100;
int eyeX = faceW * 48/100;

[ 17 ]
www.it-ebooks.info
Cartoonifier dan Kulit Changer untuk Android

int eyeY = faceH * 13/100;


Ukuran eyeSize = ukuran (eyeW, eyeH);
Mengatur sudut dan menggeser untuk mata setengah elips. int eyeA =
15; // sudut dalam derajat.
int eyeYshift = 11;
Menggambar bagian atas mata kanan. elips (faceOutline, Point (sw / 2 - eyeX,
sh / 2 - eyeY),
eyeSize, 0, 180 + eyeA, 360-eyeA, warna, ketebalan, CV_AA);
Menggambar bagian bawah mata kanan.
elips (faceOutline, Point (sw / 2 - eyeX, sh / 2 - eyeY -
eyeYshift), eyeSize, 0, 0 + eyeA, 180-eyeA, warna,
ketebalan, CV_AA);
// Menggambar bagian atas mata kiri.
elips (faceOutline, Point (sw / 2 + eyeX, sh / 2 - eyeY),
eyeSize, 0, 180 + eyeA, 360-eyeA, warna, ketebalan, CV_AA);
// Menggambar bagian bawah mata kiri.
elips (faceOutline, Point (sw / 2 + eyeX, sh / 2 - eyeY -
eyeYshift), eyeSize, 0, 0 + eyeA, 180-eyeA, warna,
ketebalan, CV_AA);

Kita dapat menggunakan metode yang sama untuk menarik bibir bawah mulut:
Menarik bibir bawah mulut. int mouthy = faceH * 48/100;int
mouthW = faceW * 45/100;
int mouthH = faceH * 6/100;
elips (faceOutline, Point (sw / 2, sh / 2 + mouthy), Size (mouthW,
mouthH), 0, 0, 180, warna, ketebalan, CV_AA);

Untuk membuatnya lebih jelas bahwa pengguna harus memasang wajah mereka di
mana ditampilkan, mari kita menulis pesan di layar!
// Menggambar teks anti-alias.
int fontFace = FONT_HERSHEY_COMPLEX;
mengapung fontScale = 1.0f;
int fontThickness = 2;
char * szMsg = "Masukan wajah Anda di sini";
putText (faceOutline, szMsg, Point (sw * 23/100, sh * 10/100),
fontFace, fontScale, warna, fontThickness, CV_AA);

Sekarang kita telah menghadapi garis ditarik, kita dapat overlay itu ke gambar
yang ditampilkan dengan menggunakan alpha blending untuk
menggabungkan gambar cartoonified dengan garis yang ditarik ini:
addWeighted (dst, 1,0, faceOutline, 0,7, 0, dst, CV_8UC3);

[ 18 ]
www.it-ebooks.info
Bab 1

Hal ini menyebabkan garis pada gambar berikut, yang menunjukkan pengguna
di mana harus menempatkan wajah mereka sehingga kita tidak perlu
mendeteksi lokasi wajah:

Pelaksanaan changer warna kulit


Daripada mendeteksi warna kulit dan kemudian daerah dengan yang warna kulit,
kita dapat menggunakan OpenCV floodfill (), Yang mirip dengan alat ember
mengisi banyak program editing gambar. Kita tahu bahwa daerah di tengah-tengah
layar harus piksel kulit (karena kami meminta pengguna untuk menempatkan wajah
mereka di tengah), sehingga untuk mengubah seluruh wajah memiliki kulit hijau,
kita hanya dapat menerapkan banjir hijau mengisi di pixel pusat, yang akan selalu
mewarnai setidaknya beberapa bagian wajah seperti hijau. Pada kenyataannya,
warna, saturasi, dan kecerahan mungkin akan berbeda di berbagai bagian wajah,
sehingga banjir mengisi jarang akan mencakup semua piksel kulit wajah kecuali
ambang batas sangat rendah sehingga hal itu juga mencakup piksel yang tidak
diinginkan di luar menghadapi. Jadi, bukannya menerapkan banjir mengisi tunggal
di tengah gambar, mari kita menerapkan banjir mengisi enam poin yang berbeda di
sekitar wajah yang harus piksel kulit.
Sebuah fitur bagus dari OpenCV floodfill ()Fungsi adalah bahwa hal itu dapat
menarik banjir mengisi menjadi sebuah gambar eksternal daripada memodifikasi
gambar input. Jadi fitur ini dapat memberi kita gambar topeng untuk
menyesuaikan warna piksel kulit tanpa harus mengubah kecerahan atau
kejenuhan, menghasilkan gambar yang lebih realistis daripada jika semua piksel
kulit menjadi pixel hijau yang identik (kehilangan signifikan rinci wajah sebagai
hasilnya).

[ 19 ]
www.it-ebooks.info
Cartoonifier dan Kulit Changer untuk Android

perubahan warna kulit tidak bekerja dengan baik dalam warna-ruang RGB. Hal ini
karena Anda ingin mengizinkan kecerahan bervariasi di wajah tapi tidak
memungkinkan warna kulit bervariasi banyak, dan RGB tidak kecerahan terpisah
dari warna. Salah satu solusi adalah dengan menggunakan warna-ruang Hue-
Saturation-Brightness (HSV), karena memisahkan kecerahan dari warna (hue) serta
colorfulness (saturasi). Sayangnya, HSV membungkus nilai hue sekitar merah, dan
karena kulit sebagian besar merah itu berarti bahwa Anda perlu untuk bekerja baik
dengan rona kurang dari 10 persen dan rona yang lebih besar dari 90 persen, karena
ini keduanya merah. Dengan demikian, kita akan sebaliknya menggunakan Y'CrCb
warna-ruang (varian dari YUV, yang di OpenCV), karena memisahkan kecerahan
dari warna, dan hanya memiliki jangkauan tunggal nilai untuk warna kulit yang
khas daripada dua. Perhatikan bahwa kamera yang paling, gambar,
Karena kita ingin modus alien kami terlihat seperti kartun, kita akan menerapkan
filter alien setelah gambar telah cartoonified; dengan kata lain, kita memiliki akses
ke gambar warna menyusut diproduksi oleh filter bilateral, dan ke tepi masker
berukuran penuh. deteksi kulit sering bekerja lebih baik pada resolusi rendah,
karena itu adalah setara dengan menganalisa nilai rata-rata tetangga masing-
masing resolusi tinggi pixel (atau sinyal frekuensi rendah bukan sinyal bising
frekuensi tinggi). Jadi mari kita bekerja di skala menyusut sama dengan filter
bilateral (setengah lebar dan setengah tinggi). Mari kita mengkonversi gambar
lukisan ke YUV:
Mat YUV = Mat (smallSize, CV_8UC3);
cvtColor (smallImg, YUV, CV_BGR2YCrCb);

Kita juga perlu untuk mengecilkan tepi masker sehingga pada skala yang sama
dengan gambar lukisan. Ada komplikasi dengan OpenCVfloodfill ()Fungsi saat
menyimpan ke gambar topeng terpisah, bahwa topeng harus memiliki batas 1-pixel
di sekitar seluruh gambar, jadi jika citra input H piksel W x dalam ukuran, gambar
topeng yang terpisah harus (W + 2) x (H + 2) piksel dalam ukuran. Tapifloodfill
()juga memungkinkan kita untuk menginisialisasi masker dengan tepi bahwa
algoritma banjir mengisi akan memastikan itu tidak menyeberang. Mari kita gunakan
fitur ini dengan harapan bahwa hal ini membantu mencegah banjir mengisi dari
memperluas luar wajah. Jadi kita perlu menyediakan dua gambar topeng: topeng
tepi yang mengukur W x H dalam ukuran, dan tepi topeng yang sama tetapi
mengukur (W + 2) x (H + 2) dalam ukuran karena harus mencakup perbatasan di
sekitar gambar. Hal ini dimungkinkan untuk memiliki beberapacv :: Mat benda
(atau header) referensi data yang sama, atau bahkan untuk memiliki cv :: Mat objek
yang referensi sub-wilayah lain cv :: Matgambar. Jadi, bukannya mengalokasikan
dua gambar terpisah dan menyalin piksel tepi masker di, mari kita mengalokasikan
gambar topeng tunggal termasuk perbatasan, dan menciptakan tambahancv ::
Matheader W x H (yang hanya merujuk daerah bunga dalam banjir mengisi topeng
tanpa perbatasan). Dengan kata lain, hanya ada satu array piksel ukuran (W + 2) x (H
+ 2) tapi duacv :: Mat benda, di mana satu adalah referensi keseluruhan (W + 2) x
(H + 2) gambar dan yang lainnya adalah referensi wilayah H W x di tengah-tengah
gambar yang:
[ 20 ]
www.it-ebooks.info
Bab 1

int sw = smallSize.width;
int sh = smallSize.height;
Mat masker, maskPlusBorder;
maskPlusBorder = Mat :: nol (sh + 2, sw + 2, CV_8UC1);
topeng = maskPlusBorder (Rect (1,1, sw, sh)); // masker di maskPlusBorder.
mengubah ukuran (tepi, masker, smallSize); // Masukan tepi di keduanya.

Tepi masker (ditampilkan di sisi kiri gambar berikut) penuh kedua tepi kuat dan
lemah; tapi kami hanya ingin tepi yang kuat, jadi kami akan menerapkan
ambang biner (menghasilkan gambar tengah pada gambar berikut). Untuk
bergabung dengan beberapa kesenjangan antara tepi kita kemudian akan
menggabungkan operator morfologimelebarkan() dan mengikis () untuk
menghapus beberapa kesenjangan (juga disebut sebagai operator "dekat"),
sehingga sisi kanan gambar:
const int EDGES_THRESHOLD = 80;
threshold (masker, masker, EDGES_THRESHOLD, 255, THRESH_BINARY);
membesar (masker, masker, Mat ());
mengikis (masker, masker, Mat ());

Seperti disebutkan sebelumnya, kami ingin menerapkan mengisi banjir di


berbagai titik di sekitar wajah untuk memastikan kami menyertakan berbagai
warna dan nuansa seluruh wajah. Mari kita memilih enam poin di sekitar
hidung, pipi, dan dahi, seperti yang ditunjukkan pada sisi kiri angka berikutnya.
Perhatikan bahwa nilai-nilai ini tergantung pada wajah garis yang ditarik
sebelumnya:
NUM_SKIN_POINTS const int = 6;
Titik skinPts [NUM_SKIN_POINTS];
skinPts [0] = Point (sw / sh / 2 - sh /
2, 6);
skinPts [1] = Point (sw / sw / sh / 2 - sh /
2 - 11, 6);
skinPts [2] = Point (sw / sw / sh / 2 - sh /
2 + 11, 6);
skinPts [3] = Point (sw / sh / 2 + sh /
2, 16);
skinPts [4] = Point (sw / sh / 2 + sh /
2 - sw / 9, 16);
skinPts [5] = Point (sw / sh / 2 + sh /
2 + sw / 9, 16);

[ 21 ]
www.it-ebooks.info
Cartoonifier dan Kulit Changer untuk Android

Sekarang kita hanya perlu menemukan beberapa batas bawah dan atas yang
baik untuk banjir mengisi. Ingatlah bahwa ini sedang dilakukan dalam ruang
warna Y'CrCb, jadi kami pada dasarnya memutuskan berapa banyak kecerahan,
komponen merah, dan komponen biru dapat bervariasi. Kami ingin
memungkinkan kecerahan untuk bervariasi banyak, untuk memasukkan
bayangan serta highlight dan refleksi, tapi kami tidak ingin warna bervariasi
banyak sekali:
const int LOWER_Y = 60;
const int UPPER_Y = 80;
const int LOWER_Cr = 25;
const int UPPER_Cr = 15;
const int LOWER_Cb = 20;
const int UPPER_Cb = 15;
Skalar (LOWER_Y, LOWER_Cr,
Skalar lowerDiff = LOWER_Cb);
Skalar (UPPER_Y, UPPER_Cr,
Skalar upperDiff = UPPER_Cb);

Kami akan menggunakan floodfill () dengan bendera default, kecuali


bahwa kita ingin menyimpan untuk masker eksternal, jadi kita harus
menentukan FLOODFILL_MASK_ONLY:
const CONNECTED_COMPONENTS int = 4; // Untuk mengisi diagonal, menggunakan 8.
const int flags = CONNECTED_COMPONENTS | FLOODFILL_FIXED_RANGE \
| FLOODFILL_MASK_ONLY;
Mat edgeMask = mask.clone (); // Simpan salinan tepi masker.
"MaskPlusBorder" diinisialisasi dengan tepi untuk memblokir floodfill
(). for (int i = 0; i <NUM_SKIN_POINTS; i ++) {
floodfill (YUV, maskPlusBorder, skinPts [i], skalar (),
NULL, lowerDiff, upperDiff, bendera);
}

Dalam gambar berikut, sisi kiri menunjukkan enam banjir mengisi lokasi (ditampilkan
sebagai lingkaran biru), dan sisi kanan angka menunjukkan topeng eksternal yang
dihasilkan, di mana kulit ditampilkan sebagai abu-abu dan tepi ditampilkan sebagai
putih. Perhatikan bahwa gambar sisi kanan dimodifikasi untuk buku ini sehingga
piksel kulit (nilai 1) yang jelas terlihat:

[ 22 ]
www.it-ebooks.info
Bab 1

Itu topeng image (ditampilkan di sisi kanan dari angka sebelumnya) sekarang berisi:
• piksel dari nilai 255 untuk piksel tepi
• piksel dari nilai 1 untuk daerah kulit
• piksel dari nilai 0 untuk sisanya

Sementara itu, edgeMaskhanya berisi piksel tepi (sebagai nilai 255). Jadi untuk
mendapatkan hanya piksel kulit, kita dapat menghapus tepi dari itu:
mask - = edgeMask;

Itu topenggambar sekarang hanya berisi 1s untuk piksel kulit dan 0s untuk
piksel non-kulit. Untuk mengubah warna kulit dan kecerahan gambar asli, kita
bisa menggunakancv :: menambahkan () dengan kulit masker untuk
meningkatkan komponen hijau pada gambar BGR asli:
int Merah = 0;
int Hijau = 70;
int Biru = 0;
tambahkan (smallImgBGR, CV_RGB (Red, Green, Blue), smallImgBGR, masker);

Gambar berikut ini menunjukkan gambar asli di sebelah kiri, dan final alien gambar
kartun di sebelah kanan, di mana setidaknya enam bagian wajah sekarang akan
menjadi hijau!

Perhatikan bahwa kita tidak hanya membuat kulit tampak hijau tetapi juga cerah
(terlihat seperti alien yang bersinar dalam gelap). Jika Anda ingin hanya mengubah
warna kulit tanpa membuatnya lebih cerah, Anda dapat menggunakan metode
berubah warna lain, seperti menambahkan 70 ke hijau sementara mengurangkan 70
dari merah dan biru, atau dikonversi ke ruang warna HSV menggunakan cvtColor
(src, dst, "CV_BGR2HSV_FULL"), Dan menyesuaikan warna dan saturasi.

Itu saja! Menjalankan aplikasi dalam mode yang berbeda sampai Anda
siap untuk port ke ponsel Anda.

[ 23 ]
www.it-ebooks.info
Cartoonifier dan Kulit Changer untuk Android

Porting dari desktop ke Android


Sekarang bahwa program itu bekerja pada desktop, kita dapat membuat sebuah aplikasi
Android atau iOS dari itu. Rincian yang diberikan di sini adalah khusus untuk Android,
tetapi juga berlaku ketika port untuk iOS untuk Apple iPhone dan iPad atau perangkat
sejenis. Ketika mengembangkan aplikasi Android, OpenCV dapat digunakan langsung
dari Jawa, tapi hasilnya tidak mungkin seefisien native C / C ++ kode dan tidak
memungkinkan menjalankan kode yang sama pada desktop seperti halnya untuk ponsel
Anda. Sehingga dianjurkan untuk menggunakan C / C ++ untuk sebagian OpenCV +
pengembangan aplikasi Android (pembaca yang ingin menulis aplikasi OpenCV murni
di Jawa dapat menggunakan JavaCV perpustakaan oleh Samuel Audet, tersedia
dihttp://code.google.com/p/javacv/, Untuk menjalankan kode yang sama pada
desktop yang kita berjalan di Android).

Proyek Android ini menggunakan kamera untuk input hidup,


sehingga tidak akan bekerja pada Emulator Android. Ini
membutuhkan perangkat nyata Android 2.2 (Froyo) atau
kemudian dengan kamera.

Antarmuka pengguna aplikasi Android harus ditulis menggunakan Java, tapi untuk
pengolahan gambar yang akan kita gunakan sama cartoon.cppC ++ file yang kita
digunakan untuk desktop. Untuk menggunakan C / C ++ kode dalam sebuah
aplikasi Android, kita harus menggunakan NDK (asli Development Kit) yang
didasarkan pada JNI (Java Native Interface). Kami akan membuat wrapper JNI
untuk kamicartoonifyImage () fungsi sehingga dapat digunakan dari Android
dengan Java.

Menyiapkan sebuah proyek


Android yang menggunakan
OpenCV
Port Android dari OpenCV berubah secara signifikan setiap tahun, seperti halnya
metode Android untuk akses kamera, sehingga buku bukan tempat terbaik untuk
menggambarkan bagaimana harus mengatur. Oleh karena itu pembaca dapat
mengikuti petunjuk terbaru dihttp: // OpenCV. org / platform / android.html
untuk mendirikan dan membangun asli (NDK) Android app dengan OpenCV. OpenCV
dilengkapi dengan contoh proyek Android disebut Sample3Native yang mengakses kamera
menggunakan OpenCV dan menampilkan gambar diubah pada layar. proyek sampel ini
berguna sebagai dasar untuk aplikasi Android yang dikembangkan dalam bab ini, sehingga
pembaca harus membiasakan diri dengan aplikasi sampel ini (saat ini tersedia
di http://docs.opencv.org/doc/tutorials/introduction/android_binary_
paket / android_binary_package_using_with_NDK.html). Kami
kemudian akan memodifikasi proyek basis Android OpenCV sehingga dapat
cartoonify frame video kamera dan menampilkan frame yang dihasilkan pada
layar.

[ 24 ]
www.it-ebooks.info
Bab 1

Jika Anda terjebak dengan perkembangan OpenCV untuk Android, misalnya


jika Anda menerima kesalahan kompilasi atau kamera selalu memberikan
frame kosong, coba cari situs ini untuk solusi:
1. Android Binary Package NDK tutorial untuk OpenCV, disebutkan sebelumnya.
2. Kelompok resmi Android-OpenCV Google (https://groups.google.com/ forum /?
fromgroups #! forum / android-OpenCV).
3. OpenCV situs Q & A (http://answers.opencv.org).
4. StackOverflow situs Q & A (http://stackoverflow.com/questions/ tag /
OpenCV + android).
5. Web (misalnya http://www.google.com).
6. Jika Anda masih tidak dapat memperbaiki masalah setelah mencoba semua ini, Anda harus
memposting pertanyaan pada kelompok Android-OpenCV Google dengan rincian pesan
kesalahan, dan sebagainya.

format warna yang digunakan untuk


pemrosesan gambar pada Android
Ketika mengembangkan untuk desktop, kita hanya harus berurusan dengan
format piksel BGR karena masukan (dari kamera, gambar, atau file video)
dalam format BGR dan begitu output (window HighGUI, gambar, atau file
video). Tapi ketika mengembangkan untuk ponsel, Anda biasanya harus
mengkonversi format warna asli sendiri.

format warna masukan dari kamera


Melihat kode contoh di JNI \ jni_part.cpp, yang myuv variabel adalah gambar
warna dalam format kamera bawaan Android: "NV21" YUV420sp. Bagian pertama
dari array adalah array pixel grayscale, diikuti oleh array berukuran setengah pixel
yang bergantian antara U dan saluran warna V. Jadi jika kita hanya ingin
mengakses gambar grayscale, kita bisa mendapatkannya langsung dari bagian
pertama dariYUV420spgambar semi-planar tanpa konversi. Tetapi jika kita ingin
gambar warna (misalnya, BGR atau format warna BGRA), kita harus
mengkonversi format warna menggunakancvtColor ().

[ 25 ]
www.it-ebooks.info
Cartoonifier dan Kulit Changer untuk Android

format warna output untuk tampilan


Melihat kode Sample3Native dari OpenCV, yang mbgravariabel adalah gambar
warna yang akan ditampilkan pada perangkat Android, dalam format BGRA.
format standar OpenCV adalah BGR (byte urutan sebaliknya dari RGB), dan BGRA
hanya menambahkan byte yang tidak terpakai pada akhir setiap pixel, sehingga
setiap pixel disimpan sebagai Biru-Green-Red -Unused. Anda juga dapat melakukan
semua proses Anda dalam standar format yang BGR OpenCV dan kemudian
mengkonversi output akhir Anda dari BGR ke BGRA sebelum tampilan di layar,
atau Anda dapat memastikan kode pengolahan gambar Anda dapat menangani
format BGRA bukan atau di samping ke format BGR. Hal ini sering dapat sederhana
untuk memungkinkan di OpenCV karena banyak fungsi OpenCV menerima BGRA,
tetapi Anda harus memastikan bahwa Anda membuat gambar dengan jumlah yang
sama kanal sebagai input, dengan melihat jikaMat :: saluran () nilai dalam
gambar Anda 3 atau 4. Juga, jika Anda langsung mengakses piksel dalam kode
Anda, Anda akan memerlukan kode terpisah untuk menangani 3-channel BGR dan
4-channel gambar BGRA.

Beberapa operasi CV berjalan lebih cepat dengan BGRA piksel


(karena sejalan dengan 32-bit) sementara beberapa berjalan lebih
cepat dengan BGR (karena memerlukan lebih sedikit memori
untuk membaca dan menulis), jadi untuk efisiensi maksimum
Anda harus mendukung kedua BGR dan BGRA dan kemudian
menemukan yang format warna berjalan secara keseluruhan
tercepat di aplikasi Anda.

Mari kita mulai dengan sesuatu yang sederhana: mendapatkan akses ke frame
kamera di OpenCV tapi tidak memproses itu, dan bukan hanya menampilkan
pada layar. Hal ini dapat dilakukan dengan mudah dengan kode Java, tetapi
penting untuk mengetahui bagaimana melakukannya menggunakan OpenCV
juga. Seperti disebutkan sebelumnya, gambar kamera tiba di kode C ++ kami
diYUV420spFormat dan harus meninggalkan dalam format BGRA. Jadi, jika kita
mempersiapkan kamicv :: Mat untuk input dan output, kita hanya perlu
mengkonversi dari YUV420sp untuk BGRA menggunakan cvtColor. Untuk
menulis C / C ++ kode untuk aplikasi Android Java, kita perlu menggunakan
nama fungsi JNI khusus yang sesuai dengan nama Java kelas dan paket yang
akan menggunakan fungsi JNI, dalam format:
JNIEXPORT <Return> JNICALL Java_ <Package> _ <Kelas> _ <Fungsi>
(JNIEnv * env, jobject, <Args>)

Jadi mari kita membuat ShowPreview () C / C ++ fungsi yang


digunakan dari CartoonifierView kelas Java dalam Cartoonifier
paket Java. Menambahkan ini ShowPreview () C / C ++ fungsi untuk
JNI \ jni_part.cpp:
Hanya menampilkan gambar kamera polos tanpa modifikasi.
JNIEXPORT batal
JNICALL Java_com_Cartoonifier_CartoonifierView_ShowPreview (JNIEnv
* env, jobject,
Jint lebar, tinggi Jint, jbyteArray YUV, jintArray bgra)
{
jbyte * _yuv = env-> GetByteArrayElements (YUV, 0);

[ 26 ]
www.it-ebooks.info
Bab 1

Jint * _bgra = env-> GetIntArrayElements (bgra, 0);

Mat myuv = Mat (tinggi + tinggi / 2, lebar, CV_8UC1, (uchar *) _


YUV); Mat mbgra = Mat (tinggi, lebar, CV_8UC4, (uchar *) _ bgra);

Mengkonversi format warna dari kamera


NV21 "YUV420sp" format untuk gambar warna Android cvtColor (myuv,
mbgra, BGRA.
CV_YUV420sp2BGRA);
OpenCV dapat sekarang akses / memodifikasi BGRA image "mbgra" ...

env-> ReleaseIntArrayElements (bgra, _bgra, 0);


env-> ReleaseByteArrayElements (YUV, _yuv, 0);
}

Sementara kode ini terlihat kompleks pada awalnya, dua baris pertama dari fungsi
hanya memberi kita akses asli array Java yang diberikan, dua baris berikutnya
membangun cv :: Mat benda di sekitar buffer pixel yang diberikan (yaitu, mereka
tidak mengalokasikan gambar baru, mereka membuat myuv mengakses piksel di
_yuv array, dan sebagainya), dan dua baris terakhir dari Fungsi melepaskan kunci
asli kita ditempatkan pada array Jawa. Satu-satunya karya nyata yang kita lakukan
dalam fungsi adalah untuk mengkonversi dari YUV ke format BGRA, sehingga
fungsi ini adalah dasar yang dapat kita gunakan untuk fungsi-fungsi baru.
Sekarang mari kita memperpanjang ini untuk menganalisis dan memodifikasi
BGRAcv :: Mat sebelum layar.

Itu JNI \ jni_part.cpp Kode contoh dalam OpenCV v2.4.2 menggunakan kode ini:
cvtColor (myuv, mbgra, CV_YUV420sp2BGR, 4);

Ini tampak seperti itu mengkonversi ke 3-channel Format BGR (format


standar OpenCV), namun karena "4"parameter sebenarnya
mengkonversi ke 4-channel BGRA (default format output Android)
sebagai gantinya! Jadi itu identik dengan kode ini, yang kurang
membingungkan:
cvtColor (myuv, mbgra, CV_YUV420sp2BGRA);

Karena kita sekarang memiliki citra BGRA sebagai input dan output bukan default OpenCV
BGR, ia meninggalkan kita dengan dua pilihan untuk bagaimana proses itu:

• Konversi dari BGRA ke BGR sebelum kita melakukan pengolahan citra kami, melakukan yang
pengolahan di BGR, dan kemudian dikonversi output ke BGRA sehingga dapat ditampilkan dengan
Android
• Memodifikasi semua kode kita untuk menangani format BGRA selain (atau bukan)
Format BGR,
jadi kita tidak perlu melakukan konversi lambat antara BGRA dan BGR
[ 27 ]
www.it-ebooks.info
Cartoonifier dan Kulit Changer untuk Android

Untuk mempermudah, kita hanya akan menerapkan konversi warna dari BGRA
BGR dan kembali, daripada mendukung baik BGR dan BGRA format. Jika Anda
menulis aplikasi real-time, Anda harus mempertimbangkan menambahkan 4-
channel BGRA dukungan dalam kode Anda untuk berpotensi meningkatkan
kinerja. Kami akan melakukan satu perubahan sederhana untuk membuat hal-hal
sedikit lebih cepat: kita mengkonversi input dariYUV420sp untuk BGRA dan
kemudian dari BGRA BGR, jadi kami mungkin juga hanya mengkonversi
langsung dari YUV420sp BGR!
Ini adalah ide yang baik untuk membangun dan menjalankan dengan ShowPreview
()Fungsi (ditunjukkan sebelumnya) pada perangkat Anda sehingga Anda memiliki
sesuatu untuk kembali ke jika Anda memiliki masalah dengan C Anda / C ++ kode
kemudian. Untuk menyebutnya dari Jawa, kita tambahkan deklarasi Jawa hanya di sebelah
deklarasi JawaCartoonifyImage () dekat bagian bawah CartoonifyView.java:
masyarakat asli kekosongan ShowPreview (int lebar,
tinggi int, byte [] YUV, int [] RGBA);

Kita kemudian dapat menyebutnya seperti contoh kode OpenCV disebut


FindFeatures (). Menempatkan ini di tengahprocessFrame () fungsi dari
CartoonifierView.java:
ShowPreview (getFrameWidth (), getFrameHeight (), data, RGBA);

Anda harus membangun dan menjalankan sekarang pada


perangkat Anda, hanya untuk melihat kamera real-time pratinjau.

Menambahkan kode cartoonifier


ke aplikasi Android NDK
Kami ingin menambahkan cartoon.cppmengajukan bahwa kita digunakan
untuk aplikasi desktop. BerkasJNI \ Android.mk set file C / C ++ / sumber
Majelis, jalur pencarian header, perpustakaan asli, dan pengaturan compiler
GCC untuk proyek Anda:
1. Tambah cartoon.cpp (dan ImageUtils_0.7.cpp jika Anda ingin lebih mudah debugging) ke
LOCAL_SRC_FILES, Tapi ingat bahwa mereka berada di folder desktop bukan default JNI map.
Jadi menambahkan ini setelah:LOCAL_SRC_FILES
: = Jni_part.cpp:
LOCAL_SRC_FILES + = ../../Cartoonifier_Desktop/cartoon.cpp
LOCAL_SRC_FILES + = ../../Cartoonifier_Desktop/ImageUtils_0.7.cpp

2. Tambahkan path file header pencarian sehingga dapat menemukan cartoon.h di folder
induk yang sama:

LOCAL_C_INCLUDES + = $ (LOCAL_PATH) /../../ Cartoonifier_Desktop

[ 28 ]
www.it-ebooks.info
Bab 1

3. Dalam JNI \ jni_part.cpp, Masukkan ini di dekat bagian atas bukannya


file #include <vector>:
# include "cartoon.h" // Cartoonifier.
# include "ImageUtils.h" // (Optional) OpenCV debugging
fungsi.

4. Tambahkan fungsi JNI CartoonifyImage ()ke berkas ini; ini akan cartoonify gambar. Kita bisa mulai
dengan menduplikasi fungsiShowPreview () kita buat sebelumnya, yang hanya menunjukkan preview
kamera tanpa memodifikasi itu.
Perhatikan bahwa kita mengubah langsung dari YUV420sp BGR
karena kita tidak ingin proses BGRA gambar:
Memodifikasi gambar kamera menggunakan filter Cartoonifier.
JNIEXPORT batal
JNICALL Java_com_Cartoonifier_CartoonifierView_CartoonifyImage (JNIEnv * env,
jobject,
Jint lebar, tinggi Jint, jbyteArray YUV, jintArray bgra)
{
Dapatkan akses asli array Java yang diberikan.
jbyte * _yuv = env-> GetByteArrayElements (YUV,
0); Jint * _bgra = env-> GetIntArrayElements
(bgra, 0);

Buat bungkus OpenCV sekitar input & output data. Mat myuv (tinggi
+ tinggi / 2, lebar, CV_8UC1, (uchar *) _ YUV); mbgra Mat (tinggi, lebar, CV_8UC4,
(uchar *) _ bgra);

Mengkonversi format warna dari kamera YUV420sp


semi-planar
Format default BGR gambar warna OpenCV.
Mat mbgr (tinggi, lebar, CV_8UC3); // Alokasikan buffer
gambar baru.
cvtColor (myuv, mbgr, CV_YUV420sp2BGR);

OpenCV sekarang dapat mengakses / memodifikasi BGR image "mbgr", dan harus
menyimpan output sebagai BGR image "displayedFrame".
Mat displayedFrame (mbgr.size (), CV_8UC3);

SEMENTARA: Hanya menampilkan gambar kamera tanpa


memodifikasi itu. displayedFrame = mbgr;

Mengkonversi output dari OpenCV BGR untuk Android BGRA //


Format.

[ 29 ]
www.it-ebooks.info
Cartoonifier dan Kulit Changer untuk Android

cvtColor (displayedFrame, mbgra, CV_BGR2BGRA);

Melepaskan kunci asli kita ditempatkan pada array Jawa. env->


ReleaseIntArrayElements (bgra, _bgra, 0); env-> ReleaseByteArrayElements (YUV, _yuv, 0);
}

5. kode sebelumnya tidak memodifikasi gambar, tapi kami ingin mengolah gambar
menggunakan cartoonifier kami kembangkan awal bab ini. Jadi sekarang mari kita masukkan
panggilan yang ada kamicartoonifyImage () fungsi yang kita buat di cartoon.cpp untuk
aplikasi desktop. menggantikan baris sementara kode displayedFrame = mbgr dengan ini:
cartoonifyImage (mbgr, displayedFrame);

6. Itu saja! Membangun kode (Eclipse harus mengkompilasi C / C ++ kode untuk Anda
menggunakanNDK-build) Dan menjalankannya pada perangkat Anda. Anda harus memiliki kerja
yang
aplikasi Cartoonifier Android (tepat di awal bab ini ada screenshot sampel
menunjukkan apa yang harus Anda harapkan)! Jika tidak membangun atau
menjalankan, kembali di atas langkah-langkah dan memperbaiki masalah
(lihat kode yang disediakan dengan buku ini jika Anda inginkan).
Lanjutkan dengan langkah selanjutnya setelah bekerja.

Meninjau aplikasi Android


Anda akan segera melihat empat masalah dengan aplikasi yang sekarang berjalan di
perangkat Anda:

• Hal ini sangat lambat; banyak detik per frame! Jadi kita hanya harus menampilkan kamera
pratinjau dan hanya cartoonify bingkai kamera ketika pengguna telah menyentuh layar untuk
mengatakan itu adalah foto yang baik.

• Perlu untuk menangani input pengguna, seperti untuk mengubah mode antara sketsa, cat, jahat,
atau mode alien. Kami akan menambahkan ini ke menu bar Android.
• Ini akan menjadi besar jika kita bisa menyimpan hasil cartoonified untuk file gambar,
untuk berbagi dengan
orang lain. Setiap kali pengguna menyentuh layar untuk gambar cartoonified, kami akan
menyimpan hasilnya sebagai file gambar pada kartu SD pengguna dan menampilkannya di Galeri
Android.
• Ada banyak suara acak di detektor tepi sketsa. Kami akan membuat khusus filter "pepper"
pengurangan kebisingan untuk menangani ini nanti.

[ 30 ]
www.it-ebooks.info
Bab 1

Cartoonifying gambar saat pengguna


mengetuk layar
Untuk menampilkan pratinjau kamera (sampai pengguna ingin cartoonify bingkai
kamera yang dipilih), kita hanya dapat memanggil ShowPreview ()Fungsi JNI kita
tulis sebelumnya. Kami juga akan menunggu untuk acara sentuhan dari pengguna
sebelum cartoonifying gambar kamera. Kami hanya ingin cartoonify satu gambar
saat pengguna menyentuh layar; oleh karena itu kami menetapkan bendera untuk
mengatakan frame kamera berikutnya harus cartoonified dan kemudian bendera
reset, sehingga berlanjut dengan kamera pratinjau lagi. Tapi ini berarti gambar
cartoonified hanya ditampilkan untuk sepersekian detik dan kemudian preview
kamera berikutnya akan ditampilkan lagi. Jadi kita akan menggunakan bendera
kedua untuk mengatakan bahwa gambar ini harus dibekukan pada layar selama
beberapa detik sebelum frame kamera menimpanya, untuk memberikan pengguna
beberapa waktu untuk melihatnya:
1. Tambahkan impor sundulan berikut dekat bagian CartoonifierApp. Jawa men
dala atas gaju
m src \ com \ Cartoonifier map: kan

impor android.view.View;
impor android.view.View.OnTouchListener;
impor android.view.MotionEvent;

2. Memodifikasi definisi kelas di dekat CartoonifierApp.java:


bagian atas
public class CartoonifierApp
meluas Kegiatan mengimplementasikan OnTouchListener {

3. Masukkan kode ini di bagian bawah onCreate () fungsi:


Panggil "onTouch ()" fungsi callback kami setiap kali pengguna
menyentuh layar.
mView.setOnTouchListener (ini);

4.Add fungsi onTouch () memproses acara sentuhan:


publik onTouch boolean (Lihat v, MotionEvent m) {
Abaikan acara gerakan jari, kita hanya peduli ketika
jari pertama menyentuh layar.
jika (m.getAction ()! = MotionEvent.ACTION_DOWN) {
return false; // Kami tidak menggunakan ini acara gerakan sentuh.
}
Log.i (TAG, "onTouch bawah event");
// Signal bahwa kita harus cartoonify frame kamera depan dan
menyimpan
itu, bukan hanya menampilkan preview.
mView.nextFrameShouldBeSaved (getBaseContext ()); kembali benar;
}

[ 31 ]
www.it-ebooks.info
Cartoonifier dan Kulit Changer untuk Android

5. Sekarang kita perlu menambahkan nextFrameShouldBeSaved ()fungsi untuk


CartoonifierView.java:
// Cartoonify frame kamera depan & simpan bukan pratinjau. void
dilindungi nextFrameShouldBeSaved (konteks Konteks) {
bSaveThisFrame = true;
}

6. Menambahkan variabel-variabel ini dekat bagian atas CartoonifierView kelas:


boolean bSaveThisFrame swasta = false;
bFreezeOutput boolean swasta = false;
private static int akhir FREEZE_OUTPUT_MSECS = 3000;

7. processFrame () fungsi dari CartoonifierViewsekarang dapat beralih antara kartun dan


pratinjau, tetapi juga harus memastikan untuk hanya menampilkan sesuatu jika tidak mencoba
untuk menampilkan gambar kartun beku selama beberapa detik. jadi gantiprocessFrame ()
dengan ini:
@Mengesampingkan
Bitmap dilindungi processFrame (byte [] data) {
Menyimpan output gambar untuk variabel anggota RGBA. int [] RGBA =
mRGBA;
Hanya memproses kamera atau memperbarui layar jika kita tidak
seharusnya hanya menampilkan gambar kartun.
jika (bFreezeOutputbFreezeOutput) {
Hanya perlu dipicu sini sekali. bFreezeOutput = false;
Tunggu beberapa detik, melakukan apa-apa! try {
menunggu (FREEZE_OUTPUT_MSECS);
} Catch (InterruptedException e)
{E.printStackTrace ();
}
kembali null;
}
if (! bSaveThisFrame) {
ShowPreview (getFrameWidth (), getFrameHeight (), data,
RGBA);
}
lain {
Hanya sekali, kemudian kembali ke modus pratinjau.
= False; bSaveThisFrame

Tidak memperbarui layar untuk sementara waktu,


sehingga pengguna dapat melihat output cartoonifier.

[ 32 ]

www.it-ebooks.info
Bab 1

bFreezeOutput = true;

CartoonifyImage (getFrameWidth (), getFrameHeight (),


data, RGBA, m_sketchMode, m_alienMode,
m_evilMode, m_debugMode);
}

Menempatkan gambar diolah menjadi obyek Bitmap yang akan


kembali untuk tampilan di layar.
Bitmap bmp = mBitmap;
bmp.setPixels (RGBA, 0, getFrameWidth (), 0, 0, getFrameWidth (),
getFrameHeight ());

kembali bmp;
}

8. Anda harus dapat membangun dan menjalankan untuk memverifikasi bahwa aplikasi
bekerja dengan baik sekarang.

Menyimpan gambar ke file dan galeri


gambar Android
Kami akan menyimpan output baik sebagai file PNG dan dipamerkan di galeri foto
Android. Galeri Android dirancang untuk file JPEG, tetapi JPEG adalah buruk bagi
gambar kartun dengan warna solid dan tepi, jadi kita akan menggunakan metode
membosankan untuk menambahkan gambar PNG ke galeri. Kami akan membuat
fungsi JavasavePNGImageToGallery ()untuk melakukan ini untuk kita. Pada bagian
bawahprocessFrame () Fungsi saja melihat sebelumnya, kita melihat bahwa Android
bitmapobjek dibuat dengan data output; jadi kita perlu cara untuk
menyimpanbitmapkeberatan ke file PNG. OpenCVimwrite ()Fungsi Java dapat
digunakan untuk menyimpan ke file PNG, tetapi ini akan memerlukan
menghubungkan kedua API Java OpenCV dan OpenCV / C ++ API C (seperti proyek
sampel OpenCV4Android "tutorial-4-campuran" tidak). Karena kita tidak perlu API
OpenCV Java untuk hal lain, kode berikut hanya akan menunjukkan cara untuk
menyimpan file PNG menggunakan API Android bukan API OpenCV Java:

1. Android bitmapkelas dapat menyimpan file ke format PNG, jadi mari kita menggunakannya.
Juga, kita perlu memilih nama file untuk gambar. Mari kita gunakan tanggal dan waktu, untuk
memungkinkan menyimpan banyak file dan sehingga memungkinkan bagi pengguna untuk
diingat ketika itu diambil. Masukkan ini sebelumkembali bmp pernyataan dari processFrame ():
jika (bFreezeOutput) {
// Dapatkan tanggal saat & waktu
SimpleDateFormat s = new SimpleDateFormat ( "yyyy-MM-dd, HH-mm-ss");

[ 33 ]

www.it-ebooks.info
Cartoonifier dan Kulit Changer untuk Android

String timestamp = s.format (Tanggal baru ());


String baseFilename = "Kartun" + timestamp + ".png";

Simpan gambar diproses sebagai file PNG pada kartu SD dan acara
di Galeri Android.
savePNGImageToGallery (bmp, mContext,
baseFilename); }

2. Tambahkan ini ke bagian atas CartoonifierView.java:


// Untuk menghemat Bitmaps untuk mengajukan dan galeri foto
Android. impor android.graphics.Bitmap.CompressFormat;
impor android.net.Uri; impor
android.os.Environment; impor
android.provider.MediaStore;
android.provider.MediaStore.Images impor;
impor android.text.format.DateFormat;
impor android.util.Log;
impor java.io.BufferedOutputStream;
impor java.io.File;
impor java.io.FileOutputStream;
import java.io.IOException; impor
java.io.OutputStream; impor
java.text.SimpleDateFormat; import
java.util.Date;

3. Masukkan ini dalam CartoonifierView kelas, di atas:


private static akhir String TAG = "CartoonifierView";
Konteks swasta mContext; // Jadi kita bisa mengakses
Android
Galeri.

4. Tambahkan ini nextFrameShouldBeSaved fungsi CartoonifierView:


ke Anda () dalam
mContext = konteks; // Simpan konteks Android, untuk GUI
mengakses.

5. Tambah savePNGImageToGallery () fungsi CartoonifierView:


kan untuk
Simpan gambar diproses sebagai file PNG pada kartu SD
dan ditampilkan di Galeri Android.
void dilindungi savePNGImageToGallery (Bitmap bmp, konteks Konteks,
String baseFilename)
{
try {
Dapatkan path file ke kartu SD. String baseFolder = \
Environment.getExternalStoragePublicDirectory (\

[ 34 ]
www.it-ebooks.info
Bab 1

Environment.DIRECTORY_PICTURES) .getAbsolutePath ()
\ + "/";
File file = new File (baseFolder + baseFilename);
Log.i (TAG, "Menyimpan gambar diproses ke file [" +
\ File.getAbsolutePath () + "]");

// Buka file.
OutputStream out = BufferedOutputStream baru (baru
FileOutputStream (file));
Simpan file gambar sebagai bmp.compress (CompressFormat.PNG, 100,
PNG. keluar);
Pastikan disimpan ke file segera, karena kita akan
untuk menambahkannya ke Galeri.
out.flush ();
out.close ();

Menambahkan file PNG ke Galeri Android. ContentValues image = baru


ContentValues (); image.put (Images.Media.TITLE, baseFilename); image.put
(Images.Media.DISPLAY_NAME, baseFilename); image.put (Images.Media.DESCRIPTION,
"Diproses oleh Cartoonifier App"); image.put
(Images.Media.DATE_TAKEN, System.currentTimeMillis ());
// msecs sejak tahun 1970 UTC. image.put
(Images.Media.MIME_TYPE, "image / png"); image.put
(Images.Media.ORIENTATION, 0); image.put
(Images.Media.DATA, file.getAbsolutePath ());
Hasil Uri =

. Context.getContentResolver () memasukkan (MediaStore.Images.Media.EXTERNAL_CONTENT_URI, gambar);

}
catch (Exception e) {
e.printStackTrace ();
}
}

6. aplikasi Android membutuhkan izin dari pengguna pada saat instalasi jika mereka perlu untuk
menyimpan file pada perangkat. Jadi masukkan baris ini diAndroidManifest.xml hanya di sebelah
garis serupa meminta izin untuk akses kamera:
<Kegunaan-izin
android: name = "android.permission.WRITE_EXTERNAL_STORAGE" />

[ 35 ]

www.it-ebooks.info
Cartoonifier dan Kulit Changer untuk Android

7. Membangun dan menjalankan aplikasi! Ketika Anda menyentuh layar untuk menyimpan foto,
Anda harus akhirnya melihat gambar cartoonified ditampilkan di layar (mungkin setelah 5 atau 10
detik dari pengolahan). Setelah itu ditampilkan di layar, itu berarti harus disimpan ke kartu SD
Anda dan ke galeri foto Anda. Keluar dari aplikasi Cartoonifier, buka aplikasi Android Gallery, dan
melihat album Foto. Anda harus melihat gambar kartun sebagai gambar PNG dalam resolusi penuh
layar Anda.

Menampilkan pesan
pemberitahuan Android tentang
gambar yang disimpan
Jika Anda ingin menampilkan pesan pemberitahuan setiap kali gambar baru disimpan
ke kartu SD dan Galeri Android, ikuti langkah-langkah; jika tidak merasa bebas untuk
melewati bagian ini:

1. Menambahkan berikut ke bagian atas CartoonifierView.java:


// Untuk menampilkan pesan Pemberitahuan saat menyimpan file.
impor android.app.Notification;
impor android.app.NotificationManager;
impor android.app.PendingIntent;
android.content.ContentValues impor;
impor android.content.Intent;

2. Tambahkan ini dekat bagian atas CartoonifierView:


int swasta mNotificationID = 0;

// Untuk menampilkan hanya 1 pemberitahuan.

3. Masukkan ini jika Pernyataan di bawah ini savePNGImageToGallery di


dalam panggilan untuk ()
processFrame ():
showNotificationMessage (mContext, baseFilename);

4. Tambah showNotificationMessage () fungsi CartoonifierView:


kan untuk
Tampilkan pesan pemberitahuan, mengatakan kita sudah
diselamatkan gambar lain. void dilindungi showNotificationMessage (konteks
Konteks, String nama file)
{
Popup pesan pemberitahuan di status Android
bar. Untuk memastikan pemberitahuan ditampilkan untuk setiap
image tapi hanya 1 disimpan di status bar pada suatu waktu,
menggunakan yang berbeda ID setiap kali
tapi menghapus pesan sebelumnya sebelum menciptakan itu.
akhir NotificationManager mgr = (NotificationManager) \

[ 36 ]
www.it-ebooks.info
Bab 1

context.getSystemService (Context.NOTIFICATION_SERVICE);

Menutup pesan popup sebelumnya, jadi kami hanya memiliki 1 // pada


satu waktu, tetapi
itu masih menunjukkan pesan popup untuk setiap // satu.
jika (mNotificationID> 0)
mgr.cancel (mNotificationID);
mNotificationID ++;

Pemberitahuan notifikasi = pemberitahuan baru


(R.drawable.icon, "Menyimpan ke galeri (image" +
mNotificationID + ") ...", System.currentTimeMillis ());
Intent intent = new Intent (konteks, CartoonifierView.class);
// Menutupnya jika pengguna mengklik di atasnya.
notification.flags | = Notification.FLAG_AUTO_CANCEL;
PendingIntent pendingIntent = PendingIntent.getActivity (konteks,
0, niat, 0); notification.setLatestEventInfo (konteks,
"Cartoonifier disimpan" + mNotificationID + "gambar ke Galeri",
"Disimpan sebagai '" + nama file + "'", pendingIntent);
mgr.notify (mNotificationID, pemberitahuan);

5. Sekali lagi, membangun dan menjalankan aplikasi! Anda akan melihat pesan pemberitahuan
muncul setiap kali Anda menyentuh layar untuk gambar lain disimpan. Jika Anda ingin pesan
pemberitahuan untuk pop up sebelum penundaan panjang pengolahan gambar daripada setelah,
memindahkan panggilan untukshowNotificationMessage () sebelum panggilan untuk
cartoonifyImage (), Dan memindahkan kode untuk menghasilkan tanggal dan waktu tali
sehingga string yang sama diberikan kepada pesan pemberitahuan dan file yang sebenarnya
disimpan.

Mengubah mode kartun melalui


menu bar Android
Mari memungkinkan pengguna untuk mengubah mode melalui menu:

1. Menambahkan header berikut di dekat bagian atas file src \ com \ Cartoonifier \
CartoonifierApp.java:
impor android.view.Menu;
impor android.view.MenuItem;

[ 37 ]
www.it-ebooks.info
Cartoonifier dan Kulit Changer untuk Android

2. Masukkan variabel anggota berikut di dalam CartoonifierApp kelas:


// Item untuk menu bar Android.
swasta MenuItem mMenuAlien;
swasta MenuItem mMenuEvil;
swasta MenuItem mMenuSketch;
swasta MenuItem mMenuDebug;

3. Menambahkan fungsi-fungsi berikut untuk CartoonifierApp:


/ ** Disebut ketika menu bar sedang dibuat oleh Android.
* / Public boolean onCreateOptionsMenu (Menu menu)
{Log.i (TAG, "onCreateOptionsMenu");
mMenuSketch = menu.add ( "Sketch atau
Painting"); mMenuAlien = menu.add ( "Alien
atau Manusia"); mMenuEvil = menu.add (
"Jahat atau Baik"); mMenuDebug = menu.add (
"[Debug Mode]"); kembali benar;
}

/ ** Disebut setiap kali pengguna menekan item menu di menu bar.


* /
public boolean onOptionsItemSelected (MenuItem item)
{Log.i (TAG, "Menu Item yang dipilih:" + item);
jika (item == mMenuSketch)
mView.toggleSketchMode ();

lain jika (item ==


mMenuAlien)
mView.toggleAlienMode ();
lain jika (item == mMenuEvil)
mView.toggleEvilMode (); lain
jika (item == mMenuDebug)
mView.toggleDebugMode ();
kembali benar;
}

4. Masukkan variabel anggota berikut di dalam CartoonifierView kelas:


boolean m_sketchMode swasta = false;
boolean m_alienMode swasta = false;
boolean m_evilMode swasta = false;
boolean m_debugMode swasta = false;

5.Add mengikuti fungsi untuk CartoonifierView:


void dilindungi toggleSketchMode () {
m_sketchMode = m_sketchMode!;
}
void dilindungi toggleAlienMode () {

[ 38 ]
www.it-ebooks.info
Bab 1

m_alienMode = m_alienMode!;
}
void dilindungi toggleEvilMode () {
m_evilMode = m_evilMode!;
}
void dilindungi toggleDebugMode () {
m_debugMode = m_debugMode!;
}

6. Kita harus lulus nilai modus ke cartoonifyImage ()kode JNI, jadi mari kita mengirim mereka
sebagai argumen. Memodifikasi deklarasi Jawa
CartoonifyImage () di CartoonifierView:
masyarakat asli kekosongan CartoonifyImage (int lebar,
int tinggi, byte [] YUV,
int [] RGBA, sketchMode boolean, alienMode
boolean, evilMode boolean, DebugMode boolean);

7. Sekarang memodifikasi kode Java sehingga kami melewati nilai-nilai modus saat ini
di processFrame ():
CartoonifyImage (getFrameWidth (), getFrameHeight (),
data, RGBA,
m_sketchMode, m_alienMode, m_evilMode, m_debugMode);

8. The JNI deklarasi CartoonifyImage () di JNI \ jni_part.cpp sekarang harus:


JNIEXPORT kekosongan JNICALL
Java_com_Cartoonifier_CartoonifierView_ CartoonifyImage (
JNIEnv * env, jobject, lebar Jint, tinggi Jint,
jbyteArray YUV, jintArray bgra, sketchMode jboolean,
alienMode jboolean, evilMode jboolean, DebugMode
jboolean)

9. Kami kemudian harus lulus mode ke C / C ++ kode dalam cartoon.cpp dari fungsi JNI di JNI \
jni_part.cpp. Ketika mengembangkan untuk Android kita hanya bisa menampilkan satu window
GUI pada satu waktu, tetapi pada desktop sangat berguna untuk menampilkan jendela ekstra saat
debugging. Jadi, bukannya mengambil bendera Boolean untukDebugMode, Mari kita lulus nomor
yang akan 0 untuk non-debug, 1 untuk debug pada ponsel (di mana menciptakan jendela GUI di
OpenCV akan menyebabkan crash!), dan 2 untuk debug pada desktop yang (di mana kita dapat
menciptakan jendela ekstra seperti yang kita inginkan):
int debugType = 0;
jika (DebugMode)
debugType = 1;

cartoonifyImage (mbgr, displayedFrame, sketchMode,


alienMode, evilMode, debugType);
[ 39 ]
www.it-ebooks.info
Cartoonifier dan Kulit Changer untuk Android

10. Update yang sebenarnya C / C ++ pelaksanaan di cartoon.cpp:


membatalkan cartoonifyImage (Mat srcColor, Mat dst, bool
sketchMode, bool alienMode, bool evilMode, int debugType) {

11. Dan memperbarui C / C ++ deklarasi di cartoon.h:


membatalkan cartoonifyImage (Mat srcColor, Mat dst, bool
sketchMode, bool alienMode, bool evilMode, int debugType);

12. Membangun dan menjalankannya; kemudian mencoba menekan kecil tombol pilihan-menu di
bagian bawah jendela. Anda harus menemukan bahwa modus sketsa adalah real-time, sedangkan
modus cat memiliki penundaan besar karena filter bilateral.

Mengurangi acak pepper noise dari


gambar sketsa
Sebagian besar kamera di smartphone saat ini dan tablet memiliki noise yang
signifikan. Hal ini biasanya dapat diterima, tetapi memiliki dampak yang besar
terhadap 5 x 5 Laplacian-tepi filter kami. Tepi masker (ditampilkan sebagai modus
sketsa) akan sering memiliki ribuan gumpalan kecil piksel hitam yang disebut
"pepper" noise, terbuat dari beberapa piksel hitam di samping satu sama lain di latar
belakang putih. Kami sudah menggunakan filter Median, yang biasanya cukup kuat
untuk menghilangkan pepper noise, tetapi dalam kasus kami itu mungkin tidak
cukup kuat. tepi masker kami sebagian besar latar belakang putih murni (nilai 255)
dengan beberapa tepi hitam (nilai 0) dan titik-titik kebisingan (juga nilai 0). Kita bisa
menggunakan operator morfologi standar penutupan, tetapi akan menghapus
banyak tepi. Jadi, sebagai gantinya, kita akan menerapkan filter khusus yang
menghilangkan daerah hitam kecil yang dikelilingi sepenuhnya oleh piksel putih.
Ini akan menghapus banyak suara sementara memiliki sedikit efek pada tepi yang
sebenarnya.
Kami akan memindai gambar untuk piksel hitam, dan pada setiap pixel hitam kami
akan memeriksa perbatasan 5 x 5 persegi di sekitarnya untuk melihat apakah semua
5 x 5 pixel perbatasan berwarna putih. Jika mereka semua putih kita tahu bahwa kita
memiliki sebuah pulau kecil kebisingan hitam, jadi kami mengisi seluruh blok
dengan piksel putih untuk menghilangkan pulau hitam. Untuk mempermudah
dalam kami 5 x 5 filter, kita akan mengabaikan dua piksel perbatasan di sekitar
gambar dan meninggalkan mereka seperti mereka.

[ 40 ]
www.it-ebooks.info
Bab 1

Gambar berikut ini menunjukkan gambar asli dari tablet Android di sisi kiri,
dengan modus sketsa di pusat (yang menunjukkan titik-titik hitam kecil pepper
noise), dan hasil dari penghapusan lada-noise kami ditampilkan di sisi kanan, di
mana kulit tampak lebih bersih:

Kode berikut dapat disebut sebagai fungsi removePepperNoise (). Fungsi ini
akan mengedit gambar di tempat untuk kesederhanaan:
kekosongan removePepperNoise (Mat & mask)
{
untuk (int y = 2; y <mask.rows-2; y ++) {
Dapatkan akses ke masing-masing 5 baris dekat pixel ini. uchar * pUp2 =
mask.ptr (y-2);
uchar * Pup 1 = mask.ptr (y-1);
uchar * pThis = mask.ptr (y);
uchar * pDown1 = mask.ptr (y + 1);
uchar * pDown2 = mask.ptr (y + 2);

Loncat pertama (dan terakhir) 2 piksel pada setiap baris. pThis + = 2;


Pup 1 + = 2;
pUp2 + = 2;
pDown1 + = 2;
pDown2 + = 2;
untuk (int x = 2; x <mask.cols-2; x ++) {
Nilai uchar = * pThis; // Dapatkan ini nilai pixel (0 atau 255).
Periksa apakah ini adalah pixel hitam yang dikelilingi oleh
piksel putih (yaitu: apakah itu sebuah "pulau" hitam). if (nilai == 0)
{

[ 41 ]

www.it-ebooks.info
Cartoonifier dan Kulit Changer untuk Android

bool atas, kiri, bawah, kanan, lingkungan;


atas = * (pUp2 - 2) && * (pUp2 - 1) && * (pUp2)
&& * (pUp2 + 1) && * (pUp2 + 2);
kiri = * (Pup 1 - 2) && * (pThis - 2) && * (pDown1 - 2);
bawah = * (pDown2 - 2) && * (pDown2 - 1) && * (pDown2)
&& * (pDown2 + 1) && * (pDown2 + 2);
kanan = * (Pup 1 + 2) && * (pThis + 2) && * (pDown1 + 2);
lingkungan = di atas && meninggalkan && bawah && benar;
jika (lingkungan == true) {
Isi blok 5x5 seluruh putih. Karena kita tahu
perbatasan 5x5 sudah putih, kita hanya perlu
mengisi daerah dalam 3x3.
* (Pup 1 - 1) = 255;
* (Pup 1 + 0) = 255;
* (Pup 1 + 1) = 255;
* (PThis - 1) = 255;
* (PThis + 0) = 255;
* (PThis + 1) = 255;
* (PDown1 - 1) = 255;
* (PDown1 + 0) = 255;
* (PDown1 + 1) = 255;
Karena kita hanya menutupi blok 5x5 keseluruhan dengan
putih, kita tahu 2 piksel berikutnya tidak akan hitam,
sehingga melewatkan 2 piksel berikutnya di sebelah kanan.
pThis + = 2;
Pup 1 + = 2;
pUp2 + = 2;
pDown1 + = 2;
pDown2 + = 2;
}
}
Pindah ke pixel berikutnya di sebelah kanan. pThis ++;
Pup 1 ++;
pUp2 ++;
pDown1 ++;
pDown2 ++;
}
}
}

[ 42 ]

www.it-ebooks.info
Bab 1

Menampilkan FPS aplikasi


Jika Anda ingin menampilkan frame per detik (FPS) mempercepat yang kurang
penting untuk aplikasi yang lambat seperti ini, tapi masih berguna-di layar, lakukan
langkah berikut:
1. Salin file src \ org \ OpenCV \ sampel \ imagemanipulations \ FpsMeter. Jawa dari folder
ImageManipulations sampel dalam OpenCV (misalnya,
C: \ OpenCV-2.4.1 \ sampel \ android \ gambar-manipulasi)
Untuk Anda src \ com \ Cartoonifier map.
2. Ganti nama paket di atas FpsMeter.java menjadi com. Cartoonifier.
3. Dalam file CartoonifierViewBase.java, Menyatakan Anda FpsMeter anggota
variabel setelah byte swasta [] mBuffer;:
swasta FpsMeter MFP;
menginisialisasi FpsMeter objek dalam CartoonifierViewBase () konstruktor,
4. setelah
mHolder.addCallback (ini);:
MFP = baru FpsMeter ();
mFps.init ();

5. Ukur FPS setiap frame di menjalankan() setelah coba tangkap


blok: mFps.measure ();

6. Gambarkan FPS ke layar untuk setiap frame, di menjalankan() setelah kanvas.


drawBitmap ()fungsi:
mFps.draw (kanvas, (canvas.getWidth () - bmp.getWidth ()) / 2, 0);

Menggunakan resolusi kamera yang berbeda


Jika Anda ingin aplikasi Anda berjalan lebih cepat, mengetahui bahwa kualitas akan
menderita, Anda pasti harus mempertimbangkan baik meminta gambar kamera
yang lebih kecil dari perangkat keras atau menyusut gambar setelah Anda
memilikinya. Kode contoh bahwa Cartoonifier didasarkan pada menggunakan
resolusi pratinjau kamera paling dekat dengan tinggi layar. Jadi jika perangkat
Anda memiliki kamera 5 megapiksel dan layar hanya 640 x 480, mungkin
menggunakan resolusi kamera 720 x 480, dan seterusnya. Jika Anda ingin
mengontrol kamera resolusi yang dipilih, Anda dapat mengubah parameter
untuksetupCamera () dalam surfaceChanged () fungsi dalam
CartoonifierViewBase.java. Sebagai contoh:

public void surfaceChanged (SurfaceHolder _holder, int Format,


int lebar, int tinggi) {
Log.i (TAG, "Ukuran layar:" + lebar + "x" + tinggi);
Menggunakan resolusi kamera kira-kira setengah tinggi layar.
setupCamera (lebar / 2, tinggi / 2);
}

[ 43 ]
www.it-ebooks.info
Cartoonifier dan Kulit Changer untuk Android

Metode yang mudah untuk mendapatkan resolusi pratinjau tertinggi dari kamera
adalah untuk lulus ukuran besar seperti 10.000 x 10.000 dan akan memilih resolusi
maksimum yang tersedia (perhatikan bahwa hal itu hanya akan memberikan
resolusi pratinjau maksimum, yang merupakan resolusi video kamera dan Oleh
karena itu seringkali jauh kurang dari resolusi masih-gambar kamera). Atau jika
Anda ingin menjalankannya benar-benar cepat, melewati 1 x 1 dan akan
menemukan resolusi pratinjau kamera termurah (misalnya 160 x 120) untuk
Anda.

Menyesuaikan aplikasi
Sekarang bahwa Anda telah membuat seluruh aplikasi Android Cartoonifier, Anda
harus mengetahui dasar-dasar cara kerjanya dan bagian mana melakukan apa;
Anda harus menyesuaikannya! Mengubah GUI, perilaku aplikasi dan alur kerja,
konstanta penyaring cartoonifier, algoritma detektor kulit, atau mengganti kode
cartoonifier dengan ide-ide Anda sendiri.
Anda dapat meningkatkan algoritma kulit-deteksi dalam banyak cara, seperti
dengan menggunakan algoritma kulit deteksi yang lebih kompleks (misalnya,
menggunakan model Gaussian dilatih dari berbagai CVPR atau konferensi ICCV
kertas terbaru di http: //www.cvpapers. com) Atau dengan menambahkan deteksi
wajah (lihat bagian Face Detection dari Bab 8, Face Recognition menggunakan
Eigenfaces) ke detektor kulit, sehingga mendeteksi di mana wajah pengguna adalah
daripada meminta pengguna untuk menempatkan wajah mereka di tengah layar .
Hati-hati bahwa deteksi wajah dapat mengambil banyak detik pada beberapa
perangkat atau kamera resolusi tinggi, sehingga pendekatan ini mungkin dibatasi
oleh kecepatan pemrosesan yang relatif lambat, tetapi smartphone dan tablet
semakin signifikan lebih cepat setiap tahun,
jadi ini akan menjadi kurang dari masalah.
Cara yang paling signifikan untuk mempercepat aplikasi visi komputer mobile
untuk mengurangi resolusi kamera sebanyak mungkin (misalnya, 0,5 megapixel
bukannya 5 megapiksel), mengalokasikan dan gambar bebas sebagai jarang
mungkin, dan melakukan konversi gambar sebagai jarang sebagai mungkin
(misalnya, dengan mendukung BGRA gambar seluruh kode Anda). Anda juga
dapat mencari gambar yang optimal pengolahan atau matematika perpustakaan
dari vendor CPU perangkat Anda (misalnya, NVIDIA Tegra, Texas Instruments
OMAP, Samsung Exynos, Apple Axe, atau Qualcomm Snapdragon) atau untuk
keluarga CPU Anda (misalnya, ARM Cortex-A9). Ingat, mungkin ada versi yang
dioptimalkan dari OpenCV untuk perangkat Anda.
Untuk membuat menyesuaikan NDK dan kode desktop yang image processing
lebih mudah, buku ini dilengkapi dengan file ImageUtils.cpp dan
ImageUtils.huntuk membantu percobaan Anda. Ini mencakup fungsi
sepertiprintMatInfo (), Yang mencetak banyak informasi tentang cv :: Matobjek,
membuat debugging OpenCV lebih mudah. Ada juga waktu macro untuk dengan
mudah menambahkan statistik waktu rinci untuk Anda C / C ++ kode. Sebagai
contoh:
DECLARE_TIMING (myFilter);

kekosongan myImageFunction (Mat img) {

[ 44 ]
www.it-ebooks.info
Bab 1

printMatInfo (img, "masukan");

START_TIMING (myFilter);
bilateralFilter (img, ...);
STOP_TIMING (myFilter);
SHOW_TIMING (myFilter, "Filter saya");
}

Anda kemudian akan melihat sesuatu seperti berikut dicetak ke konsol Anda:
masukan: 800w600h 8bpp 3ch, berbagai [19.255] [17.243] [47.251]
Filter saya: Waktu: 213ms (Ave = 215ms min = 197ms max = 312ms, di 57 berjalan).

Hal ini berguna ketika kode OpenCV Anda tidak bekerja seperti yang diharapkan;
terutama untuk pengembangan mobile di mana seringkali cukup sulit untuk
menggunakan debugger IDE, danprintf () pernyataan umumnya tidak akan
bekerja di Android NDK. Namun, fungsi dalam ImageUtils bekerja pada kedua
Android dan desktop.

Ringkasan
Bab ini telah menunjukkan beberapa jenis filter image processing yang dapat
digunakan untuk menghasilkan berbagai efek kartun: mode sketsa polos yang
terlihat seperti gambar pensil, modus cat yang terlihat seperti lukisan warna, dan
mode kartun yang menghamparkan modus sketsa di atas modus cat untuk
membuat gambar tampak seperti kartun. Hal ini juga menunjukkan bahwa efek
menyenangkan lainnya dapat diperoleh, seperti modus kejahatan yang sangat
meningkatkan tepi berisik, dan modus alien yang mengubah kulit wajah tampak
hijau terang.
Ada banyak aplikasi smartphone komersial yang melakukan efek menyenangkan yang
sama pada wajah pengguna, seperti filter kartun dan penukaran warna kulit. Ada juga
alat profesional menggunakan konsep serupa, seperti alat-alat video pasca-pengolahan
kulit-smoothing yang berusaha untuk mempercantik wajah perempuan dengan
menghaluskan kulit mereka sambil menjaga tepi dan daerah non-kulit yang tajam, untuk
membuat wajah mereka tampak lebih muda.

Bab ini menunjukkan bagaimana port aplikasi dari aplikasi desktop ke aplikasi
seluler Android, dengan mengikuti pedoman yang direkomendasikan
mengembangkan versi desktop kerja pertama, porting ke aplikasi mobile, dan
menciptakan user interface yang cocok untuk aplikasi seluler . Kode gambar-
pengolahan dibagi antara dua proyek sehingga pembaca dapat memodifikasi filter
kartun untuk aplikasi desktop, dan dengan membangun kembali aplikasi Android
secara otomatis harus menunjukkan modifikasi mereka di aplikasi Android juga.

[ 45 ]
www.it-ebooks.info
Cartoonifier dan Kulit Changer untuk Android

Langkah-langkah yang diperlukan untuk menggunakan OpenCV4Android


mengubah secara teratur, dan pengembangan Android itu sendiri tidak statis;
sehingga bab ini menunjukkan bagaimana membangun aplikasi Android dengan
menambahkan fungsionalitas untuk salah satu proyek sampel OpenCV.
Diharapkan pembaca dapat menambahkan fungsi yang sama untuk sebuah proyek
yang setara di masa depan versi OpenCV4Android.
Buku ini termasuk kode sumber untuk kedua proyek desktop dan proyek Android.

[ 46 ]
www.it-ebooks.info
Berbasis penanda
Augmented
Kenyataan di iPhone atau
iPad
augmented reality (AR) adalah pandangan hidup dari lingkungan dunia nyata
yang unsur-unsurnya ditambah dengan grafis yang dihasilkan komputer.
Akibatnya, teknologi fungsi dengan meningkatkan persepsi seseorang saat realitas.
Augmentation adalah konvensional secara real-time dan dalam konteks semantik
dengan unsur-unsur lingkungan. Dengan bantuan teknologi AR canggih (misalnya,
menambahkan visi komputer dan pengenalan obyek) informasi tentang dunia nyata
sekitar pengguna menjadi interaktif dan dapat dimanipulasi secara digital.
Informasi buatan tentang lingkungan dan benda-benda yang dapat dilakukan
overlay pada dunia nyata.
Dalam bab ini kita akan membuat aplikasi AR untuk perangkat iPhone / iPad.
Mulai dari awal, kita akan membuat sebuah aplikasi yang menggunakan spidol
untuk menggambar beberapa objek buatan pada gambar yang diperoleh dari
kamera. Anda akan belajar bagaimana untuk membuat sebuah proyek di Xcode IDE
dan mengkonfigurasinya untuk menggunakan OpenCV dalam aplikasi Anda. Juga,
aspek seperti menangkap video dari built-in kamera, adegan 3D rendering
menggunakan OpenGL ES, dan bangunan arsitektur aplikasi AR umum akan
dijelaskan.
Sebelum kita mulai, izinkan saya memberi Anda daftar singkat dari pengetahuan dan perangkat lunak
yang Anda akan perlu:

• Anda akan membutuhkan komputer Apple dengan Xcode IDE diinstal. Perkembangan dari
aplikasi untuk iPhone / iPad hanya mungkin dengan Apple Xcode IDE. Ini adalah satu-satunya
cara untuk membangun aplikasi untuk platform ini.
• Anda akan membutuhkan model perangkat sentuh iPhone, iPad, atau iPod. Untuk menjalankan
Anda aplikasi pada perangkat, Anda akan harus membeli Apple Developer
Sertifikat untuk USD 99 per tahun. Tidak mungkin untuk
menjalankan aplikasi yang dikembangkan pada perangkat
tanpa sertifikat ini.
www.it-ebooks.info
Augmented Reality penanda berbasis pada iPhone atau iPad

• Anda juga akan membutuhkan pengetahuan dasar tentang Xcode IDE. Kami akan
menganggap pembaca memiliki beberapa pengalaman menggunakan IDE ini.
• pengetahuan dasar tentang Objective-C dan C ++ bahasa pemrograman juga
diperlukan.
Namun, semua bagian kompleks dari kode sumber aplikasi akan dijelaskan secara rinci.
Dari bab ini Anda akan belajar lebih banyak tentang spidol. Rutinitas Deteksi
penuh dijelaskan. Setelah membaca bab ini Anda akan dapat menulis algoritma
deteksi penanda Anda sendiri, memperkirakan penanda berpose di dunia 3D
berkaitan dengan kamera berpose, dan menggunakan transformasi ini di antara
mereka untuk memvisualisasikan objek 3D sewenang-wenang.
Anda akan menemukan proyek contoh media buku ini untuk bab ini. Ini
adalah titik awal yang baik untuk membuat aplikasi Reality Anda mobile
pertama Augmented.
Dalam bab ini, kita akan membahas topik-topik berikut:
• Membuat proyek iOS yang menggunakan OpenCV
• arsitektur aplikasi
• deteksi penanda
• identifikasi penanda
• Pengakuan kode penanda
• Menempatkan penanda dalam 3D
• Rendering objek virtual 3D

Membuat proyek iOS yang


menggunakan OpenCV
Pada bagian ini kita akan membuat sebuah aplikasi demo untuk perangkat iPhone /
iPad yang akan menggunakan OpenCV (Open Source Computer Vision)
perpustakaan untuk mendeteksi penanda dalam bingkai kamera dan membuat objek
3D di atasnya. Contoh ini akan menunjukkan cara untuk mendapatkan akses ke aliran
data video mentah dari kamera perangkat, melakukan pengolahan citra
menggunakan perpustakaan OpenCV, menemukan penanda dalam gambar, dan
membuat overlay AR.

[ 48 ]
www.it-ebooks.info
Bab 2

Kami akan mulai dengan terlebih dahulu menciptakan sebuah proyek Xcode
baru dengan memilih template iOS Tunggal View Application, seperti yang
ditunjukkan pada gambar berikut:

Sekarang kita harus menambahkan OpenCV untuk proyek kami. Langkah ini
diperlukan karena dalam aplikasi ini kita akan menggunakan banyak fungsi dari
perpustakaan ini untuk mendeteksi penanda dan memperkirakan posisi posisi.
OpenCV adalah library dari fungsi pemrograman untuk real-time visi komputer.
Ini pada awalnya dikembangkan oleh Intel dan kini didukung oleh Willow Garage
dan Itseez. Perpustakaan ini ditulis dalam C dan C ++ bahasa. Ia juga memiliki
Python resmi mengikat dan binding tidak resmi dengan bahasa Java dan .NET.

Menambahkan kerangka OpenCV


Untungnya perpustakaan adalah cross-platform, sehingga dapat digunakan pada
perangkat iOS. Mulai dari versi 2.4.2, OpenCV perpustakaan secara resmi
didukung pada platform iOS dan Anda dapat men-download paket distribusi
dari perpustakaanwebsite di http: // opencv.org/. Itu OpenCV untuk iOS
Link poin ke terkompresi Kerangka OpenCV. Jangan khawatir jika Anda baru
untuk pengembangan iOS; kerangka seperti bundel file. Biasanya setiap paket
kerangka berisi daftar file header dan daftar pustaka statis terkait. kerangka
aplikasi menyediakan cara mudah untuk mendistribusikan perpustakaan
dikompilasi untuk pengembang.

[ 49 ]
www.it-ebooks.info
Augmented Reality penanda berbasis pada iPhone atau iPad

Tentu saja, Anda dapat membangun perpustakaan Anda sendiri dari awal.
dokumentasi OpenCV menjelaskan proses ini secara rinci. Untuk mempermudah,
kita mengikuti cara yang disarankan dan menggunakan kerangka kerja untuk bab
ini.
Setelah men-download file kita ekstrak isinya ke folder proyek, seperti yang
ditunjukkan pada gambar berikut:

Untuk menginformasikan Xcode IDE untuk menggunakan kerangka apapun


selama tahap membangun, klik pada pilihan Proyek dan cari tab fase Build. Dari
sana kita bisa menambahkan atau menghapus daftar kerangka kerja yang terlibat
dalam proses membangun. Klik pada tanda plus untuk menambahkan sebuah
kerangka kerja baru, seperti yang ditunjukkan pada gambar berikut:

[ 50 ]
www.it-ebooks.info
Bab 2

Dari sini kita bisa memilih dari daftar kerangka standar. Tapi untuk menambah
kerangka kustom kita harus klik pada tombol Add lainnya. Kotak dialog file
yang terbuka akan muncul. Arahkan ke opencv2.framework dalam folder
proyek seperti yang ditunjukkan pada gambar berikut:

Termasuk header OpenCV


Sekarang kita telah menambahkan kerangka OpenCV untuk proyek, semuanya
hampir selesai. Satu hal terakhir-mari kita tambahkan header OpenCV untuk
header dikompilasi proyek. Header dikompilasi adalah fitur yang hebat untuk
mempercepat waktu kompilasi. Dengan menambahkan header OpenCV kepada
mereka, semua sumber Anda secara otomatis termasuk OpenCV header juga.
Menemukan sebuah.pch file dalam sumber pohon proyek dan memodifikasinya
dengan cara berikut.
Kode berikut menunjukkan bagaimana memodifikasi .pch mengajukan di pohon proyek
sumber:
//
sundulan awalan untuk semua file sumber 'Example_MarkerBasedAR'

#import <Availability.h>

#ifndef __IPHONE_5_0

[ 51 ]
www.it-ebooks.info
Augmented Reality penanda berbasis pada iPhone atau iPad

#warning "Proyek ini menggunakan fitur hanya tersedia di iOS SDK


5.0 dan kemudian."
#berakhir jika

#ifdef __cplusplus
#include <opencv2 / opencv.hpp>
#berakhir jika

#ifdef __OBJC__
#import <UIKit / UIKit.h>
#import <Foundation / Foundation.h>
#berakhir jika

Sekarang Anda dapat memanggil fungsi OpenCV dari tempat manapun dalam proyek
Anda.

Itu saja. Template proyek kami dikonfigurasi dan kami siap untuk bergerak
lebih lanjut. saran gratis: membuat salinan dari proyek ini; ini akan
menghemat waktu saat Anda sedang menciptakan satu berikutnya!

arsitektur aplikasi
Setiap aplikasi iOS berisi setidaknya satu contoh dari
UIViewControllerantarmuka yang menangani semua lihat acara dan mengelola
logika bisnis aplikasi. Kelas ini menyediakan model pandangan-manajemen yang
mendasar untuk semua aplikasi iOS. Sebuah controller pandangan mengelola satu
set pandangan yang membentuk sebagian dari antarmuka pengguna aplikasi
Anda. Sebagai bagian dari pengendali lapisan aplikasi Anda, pandangan
controller mengkoordinasikan upaya-upaya dengan model yang objek dan benda-
termasuk kontroler lainnya pengendali tampilan-jadi lain aplikasi menyajikan
antarmuka pengguna tunggal yang koheren.
Aplikasi yang kita akan menulis akan memiliki hanya satu tampilan; itu sebabnya
kami memilih template Single-View Aplikasi untuk membuat satu. Pandangan ini
akan digunakan untuk menyajikan gambar yang diberikan. Kami ViewController
kelas akan berisi tiga komponen utama yang setiap aplikasi AR harus memiliki (lihat
diagram berikutnya):

• sumber video
• pipa pengolahan
• mesin visualisasi

[ 52 ]
www.it-ebooks.info
Bab 2

Sumber video bertanggung jawab untuk menyediakan frame baru yang diambil
dari kamera built-in untuk kode pengguna. Ini berarti bahwa sumber video
harus mampu memilih perangkat kamera (kamera depan atau belakang
menghadap), menyesuaikan parameter (seperti resolusi video yang diambil,
white balance, dan kecepatan rana), dan meraih frame tanpa pembekuan UI
utama.
Pengolahan citra rutin akan dirumuskan dalam MarkerDetectorkelas. Kelas ini
menyediakan antarmuka yang sangat tipis untuk kode pengguna. Biasanya itu
satu set fungsi sepertiprocessFrame dan getResult. Sebenarnya itu semua
yangViewControllerharus tahu tentang. Kita tidak harus mengekspos struktur
data tingkat rendah dan algoritma untuk lapisan tampilan tanpa keharusan yang
kuat.VisualizationController berisi semua logika yang bersangkutan dengan
visualisasi dari Augmented Reality pada pandangan kita.
VisualizationController juga fasad yang menyembunyikan tertentu
pelaksanaan mesin rendering. Rendah koherensi kode memberi kita kebebasan
untuk mengubah komponen ini tanpa perlu menulis ulang sisa kode Anda.
Pendekatan seperti ini memberi Anda kebebasan untuk menggunakan modul
independen pada platform lain dan kompiler juga. Sebagai contoh, Anda dapat
menggunakanMarkerDetectorkelas mudah untuk mengembangkan aplikasi
desktop pada sistem Mac, Windows, dan Linux tanpa perubahan kode.
Demikian juga, Anda dapat memutuskan untuk
pelabuhanVisualizationController pada platform Windows dan
menggunakan Direct3D untuk rendering. Dalam hal ini Anda harus menulis
hanya baruVisualizationControllerpelaksanaan; bagian kode lain akan tetap
sama.

[ 53 ]
www.it-ebooks.info
Augmented Reality penanda berbasis pada iPhone atau iPad

Rutin pengolahan utama dimulai dari menerima bingkai baru dari sumber video.
Hal ini memicu sumber video untuk menginformasikan kode pengguna tentang acara ini
dengan callback.
ViewController menangani callback ini dan melakukan operasi berikut:

1. Mengirimkan sebuah frame baru untuk controller visualisasi.


2. Melakukan pengolahan frame baru menggunakan pipa kami.
3. Mengirim penanda terdeteksi ke tahap visualisasi.
4. Renders adegan.

Mari kita memeriksa rutin ini secara rinci. Render adegan AR termasuk gambar
gambar latar belakang yang memiliki kandungan frame terakhir yang diterima;
objek 3D buatan diambil nanti. Ketika kita mengirim frame baru untuk visualisasi,
kita menyalin gambar data ke buffer internal mesin rendering. Ini bukan render
yang sebenarnya belum; kita hanya memperbarui teks dengan bitmap baru.
Langkah kedua adalah pengolahan bingkai baru dan deteksi penanda. Kami melewati
citra kami sebagai masukan dan sebagai hasilnya menerima daftar penanda terdeteksi.
di atasnya. tanda tersebut dilewatkan ke controller visualisasi, yang tahu bagaimana
untuk menangani mereka. Mari kita lihat diagram urutan berikut di mana rutinitas ini
ditunjukkan:

[ 54 ]
www.it-ebooks.info
Bab 2

Kami memulai pembangunan dengan menulis komponen video capture. Kelas ini
akan bertanggung jawab untuk semua bingkai meraih dan untuk mengirimkan
pemberitahuan frame ditangkap melalui pengguna callback. Kemudian kita akan
menulis algoritma deteksi penanda. rutin deteksi ini adalah inti dari aplikasi Anda.
Dalam hal ini bagian dari program kami kami akan menggunakan banyak fungsi
OpenCV untuk memproses gambar, mendeteksi kontur pada mereka, menemukan
persegi panjang penanda, dan memperkirakan posisi mereka. Setelah itu kita akan
berkonsentrasi pada visualisasi dari hasil kami menggunakan Augmented Reality.
Setelah membawa semua hal-hal ini bersama-sama kita akan menyelesaikan
aplikasi AR pertama kami. Jadi mari kita lanjutkan!

Mengakses kamera
Aplikasi Augmented Reality adalah mustahil untuk membuat tanpa dua hal utama:
menangkap video dan AR visualisasi. Tahap video capture terdiri dari menerima
frame dari kamera perangkat, melakukan konversi warna yang diperlukan, dan
mengirimkannya ke pipa pengolahan. Sebagai kerangka waktu pemrosesan tunggal
sangat penting untuk aplikasi AR, proses penangkapan harus seefisien mungkin.
Cara terbaik untuk mencapai performa maksimal adalah untuk memiliki akses
langsung ke frame yang diterima dari kamera. Hal ini menjadi mungkin mulai dari
iOS Versi 4. ada API dari kerangka AVFoundation menyediakan fungsionalitas yang
diperlukan untuk membaca langsung dari buffer gambar dalam memori.
Anda dapat menemukan banyak contoh yang menggunakan
AVCaptureVideoPreviewLayer kelas dan UIGetScreenImageberfungsi untuk
menangkap video dari kamera. Teknik ini digunakan untuk iOS Versi 3 dan
sebelumnya. Sekarang telah menjadi usang dan memiliki dua kelemahan utama:
• Kurangnya akses langsung ke frame data. Untuk mendapatkan bitmap, Anda harus membuat
perantara contoh UIImage, Menyalin gambar untuk itu, dan mendapatkannya kembali. Untuk aplikasi
AR harga ini terlalu tinggi, karena setiap hal milidetik. Kehilangan beberapa frame per detik (FPS)
secara signifikan mengurangi pengalaman pengguna secara keseluruhan.
• Untuk menggambar AR, Anda harus menambahkan pandangan overlay transparan yang akan
hadir AR. Mengacu pada pedoman Apple, Anda harus menghindari lapisan non-opak karena
pencampuran mereka sulit untuk prosesor mobile.
kelas-kelas AVCaptureDevice dan AVCaptureVideoDataOutputmemungkinkan
Anda untuk mengkonfigurasi, menangkap, dan menentukan frame video
diproses di 32 Format bpp BGRA. Anda juga dapat mengatur resolusi yang
diinginkan dari frame output. Namun, hal itu mempengaruhi kinerja
keseluruhan sejak lebih besar frame waktu pemrosesan lebih dan memori
diperlukan.

[ 55 ]
www.it-ebooks.info
Augmented Reality penanda berbasis pada iPhone atau iPad

Ada alternatif yang baik untuk kinerja tinggi video capture. The AVFoundation
API menawarkan cara yang lebih cepat dan lebih elegan untuk ambil frame
langsung dari kamera. Tapi pertama-tama, mari kita lihat gambar berikut di mana
proses penangkapan untuk iOS ditunjukkan:

AVCaptureSession adalah akar menangkap objek yang kita harus menciptakan.


Menangkap Sesi membutuhkan dua komponen-input dan output. Perangkat
input baik dapat menjadi perangkat fisik (kamera) atau file video (tidak
ditampilkan dalam diagram). Dalam kasus kami itu built-in kamera (depan atau
belakang). Perangkat output dapat disajikan oleh salah satu antarmuka berikut:
• AVCaptureMovieFileOutput
• AVCaptureStillImageOutput
• AVCaptureVideoPreviewLayer
• AVCaptureVideoDataOutput

Itu AVCaptureMovieFileOutput antarmuka digunakan untuk merekam video ke


file, AVCaptureStillImageOutput antarmuka digunakan untuk membuat
gambar diam, dan AVCaptureVideoPreviewLayer antarmuka digunakan untuk
memainkan video preview pada layar. Kami tertarik
padaAVCaptureVideoDataOutput antarmuka karena memberikan Anda akses
langsung ke data video.

Platform iOS dibangun di atas bahasa pemrograman Objective-C.


Jadi untuk bekerja dengan kerangka AVFoundation, kelas kami
juga harus ditulis di Objective-C. Pada bagian ini daftar kode
berada di Objective-C bahasa ++.

[ 56 ]
www.it-ebooks.info
Bab 2

Untuk merangkum proses menangkap video, kami membuat VideoSource


antarmuka seperti yang ditunjukkan oleh kode berikut:
@protocol VideoSourceDelegate <NSObject>

- (void) frameReady: (BGRAVideoFrame) bingkai;

@akhir

@ interface VideoSource: NSObject


<AVCaptureVideoDataOutputSampleBuffe rDelegate>
{

@ property (nonatomic, mempertahankan) AVCaptureSession *


captureSession; @ property (nonatomic, mempertahankan)
AVCaptureDeviceInput * deviceInput; @ property (nonatomic,
mempertahankan) id <VideoSourceDelegate> delegasi;

- (Bool) startWithDevicePosition: (AVCaptureDevicePosition) devicePosition;


- (CameraCalibration) getCalibration;
- (CGSize) getFrameSize;

@akhir

Dalam callback ini kita mengunci buffer gambar untuk mencegah modifikasi oleh
setiap frame baru, mendapatkan pointer ke data gambar dan bingkai dimensi.
Kemudian kita membangun objek BGRAVideoFrame sementara yang diteruskan
ke luar melalui delegasi khusus. delegasi ini memiliki berikut prototipe:
@protocol VideoSourceDelegate <NSObject>
- (void) frameReady: (BGRAVideoFrame) bingkai;

@akhir

Dalam VideoSourceDelegate, yang VideoSource antarmuka menginformasikan


kode pengguna yang bingkai baru tersedia.

[ 57 ]

www.it-ebooks.info
Augmented Reality penanda berbasis pada iPhone atau iPad

Langkah-demi-langkah panduan untuk inisialisasi video capture terdaftar sebagai berikut:

1. Membuat sebuah instance dari AVCaptureSession dan mengatur preset capture


kualitas sesi.
2. Pilih dan menciptakan AVCaptureDevice. Anda dapat memilih kamera depan atau
belakang menghadap atau menggunakan default.
3. Inisialisasi AVCaptureDeviceInput menggunakan perangkat menangkap dibuat dan
menambahkannya ke sesi capture.
4. Buat instance dari AVCaptureVideoDataOutput dan menginisialisasi dengan format frame
video, callback delegasi, dan pengiriman antrian.
5. Tambahkan menangkap output ke objek sesi capture.
6. Mulai sesi capture.

Mari kita menjelaskan beberapa langkah ini secara lebih rinci. Setelah membuat
sesi capture, kita dapat menentukan ditetapkan kualitas yang diinginkan untuk
memastikan bahwa kita akan mendapatkan kinerja yang optimal. Kita tidak perlu
untuk memproses video berkualitas HD, jadi 640 x 480 atau resolusi bingkai
bahkan lebih rendah adalah pilihan yang baik:
- (Id) init
{
if ((self = [Super init]))
{
AVCaptureSession * capSession = [[AVCaptureSession alloc] init];

if ([capSession canSetSessionPreset:
AVCaptureSessionPreset64 0x480])
{
[CapSession setSessionPreset: AVCaptureSessionPreset640x480];
NSLog (@ "Set sesi capture yang telah ditetapkan
AVCaptureSessionPreset640x480" );
}
lain jika ([capSession canSetSessionPreset: AVCaptureSessionPresetL
ow])
{
[CapSession setSessionPreset: AVCaptureSessionPresetLow]; NSLog (@
"Set sesi capture diatur AVCaptureSessionPresetLow");
}

self.captureSession = capSession;
}
kembali diri;
}

[ 58 ]
www.it-ebooks.info
Bab 2

Selalu periksa kemampuan perangkat keras dengan


menggunakan API yang sesuai; tidak ada jaminan bahwa
setiap kamera akan mampu menetapkan ditetapkan sesi
tertentu.

Setelah membuat sesi capture, kita harus menambahkan penangkapan


masukan-contoh AVCaptureDeviceInputakan mewakili perangkat kamera
fisik. ItucameraWithPosition fungsi fungsi pembantu yang mengembalikan
perangkat kamera untuk posisi yang diminta (depan, belakang, atau default):
- (Bool) startWithDevicePosition: (AVCaptureDevicePosition) devicePosition
{
AVCaptureDevice * videoDevice = [self cameraWithPosition: ion
devicePosit];

if (! videoDevice)
kembali FALSE;

{
NSError * kesalahan;

AVCaptureDeviceInput * videoIn = [AVCaptureDeviceInput


deviceInputWithDevice: videoDevice error: & error];
self.deviceInput = videoIn;

if (error!)
{
if ([[self captureSession] canAddInput: videoIn])
{
[[Self captureSession] addInput: videoIn];
}
lain
{
NSLog (@ "Tidak dapat menambahkan input video");
kembali FALSE;
}
}
lain
{
NSLog (@ "Tidak dapat membuat input video");
kembali FALSE;
}

[ 59 ]

www.it-ebooks.info
Augmented Reality penanda berbasis pada iPhone atau iPad

[Self addRawViewOutput];
[CaptureSession startRunning];
mengembalikan TRUE;
}

Harap perhatikan kode penanganan error. Jaga nilai kembali untuk hal penting seperti
bekerja dengan pemasangan perangkat keras adalah praktik yang baik. Tanpa ini, kode
Anda dapat crash dalam kasus-kasus yang tak terduga tanpa memberitahu pengguna
apa yang telah terjadi.
Kami menciptakan sesi menangkap dan menambahkan sumber frame video.
Sekarang saatnya untuk menambahkan penerima-objek yang akan menerima data
bingkai yang sebenarnya. ItuAVCaptureVideoDataOutput kelas digunakan untuk
memproses frame terkompresi dari aliran video. Kamera ini dapat memberikan
frame di BGRA, CMYK, atau model warna grayscale sederhana. Untuk tujuan kita
model warna BGRA cocok terbaik dari semua, karena kita akan menggunakan
frame ini untuk visualisasi dan pengolahan gambar. Kode berikut
menunjukkanaddRawViewOutput fungsi:
- (Void) addRawViewOutput
{
/ * Kami setupt output * /
AVCaptureVideoDataOutput * captureOutput =
[[AVCaptureVideoDataOutput alloc] init];

/*Sementara Sebuah bingkai aku s proses di -


captureOutput: didOutputSampleBuff er: fromConnection: metode
delegasi tidak ada frame lainnya ditambahkan dalam antrian.
Jika Anda tidak ingin perilaku ini mengatur properti
untuk NO * / captureOutput.alwaysDiscardsLateVideoFrames
= YES;

/ * Kami membuat antrian serial untuk menangani pengolahan frame


kami * / antrian dispatch_queue_t;
antrian = dispatch_queue_create ( "com.Example_MarkerBasedAR.
cameraQueue",
BATAL);
[CaptureOutput setSampleBufferDelegate: antrian diri:
antrian]; dispatch_release (antrian);

Mengatur output video ke toko bingkai di BGRA (Hal ini


seharusnya menjadi lebih cepat)
NSString * key = (NSString *) kCVPixelBufferPixelFormatTypeKey;
NSNumber * value = [NSNumber

[ 60 ]
www.it-ebooks.info
Bab 2

numberWithUnsignedInt: kCVPixelFormatType_32BGRA];

NSDictionary * videoSettings =
[NSDictionary dictionaryWithObject: nilai
forKey: key];
[CaptureOutput setVideoSettings: videoSettings];

// Register output
[Self.captureSession addOutput: captureOutput];
}

Sekarang sesi capture akhirnya dikonfigurasi. Ketika mulai, itu akan menangkap frame
dari kamera dan mengirimkannya ke kode pengguna. Ketika frame baru tersedia,
sebuahAVCaptureSession objek melakukan captureOutput:
didOutputSampleBuffer: fromConnection callback. Dalam fungsi ini, kita akan
melakukan konversi data minor operasi untuk mendapatkan data gambar dalam format
yang lebih bermanfaat dan menyebarkannya ke kode pengguna:

- (Void) captureOutput: (AVCaptureOutput *)


captureOutput didOutputSampleBuffer: (CMSampleBufferRef)
sampleBuffer fromConnection: (AVCaptureConnection *) koneksi
{
Dapatkan frame video memegang gambar penyangga
CVImageBufferRef imageBuffer = CMSampleBufferGetImageBuffer
(sampleB uffer);

Mengunci gambar penyangga CVPixelBufferLockBaseAddress (imageBuffer, 0);

Dapatkan informasi tentang gambar


uint8_t * BaseAddress = (uint8_t *) CVPixelBufferGetBaseAddress (image
Penyangga);
width size_t = CVPixelBufferGetWidth (imageBuffer); size_t
height = CVPixelBufferGetHeight (imageBuffer); size_t
langkah = CVPixelBufferGetBytesPerRow (imageBuffer);

BGRAVideoFrame bingkai = {lebar, tinggi, langkahnya,


BaseAddress}; [Mendelegasikan frameReady: bingkai];

/ * Kami membuka gambar penyangga * /


CVPixelBufferUnlockBaseAddress (imageBuffer,
0);
}

[ 61 ]
www.it-ebooks.info
Augmented Reality penanda berbasis pada iPhone atau iPad

Kami mendapatkan referensi ke buffer gambar yang menyimpan data bingkai


kami. Kemudian kita menguncinya untuk mencegah modifikasi oleh frame baru.
Sekarang kita memiliki akses eksklusif ke frame data. Dengan bantuan dari API
CoreVideo, kita mendapatkan dimensi gambar, langkah (jumlah pixel per baris),
dan pointer ke awal data gambar.

Aku menarik perhatian Anda ke


CVPixelBufferLockBaseAddress/
CVPixelBufferUnlockBaseAddress fungsi panggilan di panggil
balik kode. Sampai kita memegang kunci pada buffer pixel, ia
menjamin konsistensi dan kebenaran datanya. Membaca piksel
tersedia hanya setelah Anda telah mendapatkan kunci. Setelah
selesai, jangan lupa untuk membuka kunci untuk memungkinkan OS
untuk mengisinya dengan data baru.

deteksi penanda
Sebuah penanda biasanya dirancang sebagai gambar persegi panjang memegang
area hitam dan putih di dalamnya. Karena keterbatasan diketahui, prosedur deteksi
penanda adalah sederhana. Pertama-tama kita perlu mencari kontur tertutup pada
gambar input dan unwarp gambar di dalamnya untuk persegi panjang dan
kemudian memeriksa ini terhadap model yang penanda kami.
Dalam contoh ini 5 x 5 penanda akan digunakan. Berikut adalah apa yang tampak seperti:

[ 62 ]
www.it-ebooks.info
Bab 2

Dalam proyek sampel yang Anda akan menemukan dalam buku ini, rutin
deteksi penanda dirumuskan dalam MarkerDetector kelas:
/ **
* Sebuah kelas tingkat atas yang merangkum algoritma detektor penanda
* /
kelas MarkerDetector
{
publik:

/ **
* Menginisialisasi contoh baru dari objek penanda detektor
* @calibration [di] - kalibrasi Kamera diperlukan untuk estimasi berpose.
* /
MarkerDetector (CameraCalibration kalibrasi);

membatalkan processFrame (const BGRAVideoFrame & frame);

std const :: vector <Transformasi> & getTransformations () const;

terlindung:
findMarkers bool (const BGRAVideoFrame & bingkai,
std :: vector <Marker> & detectedMarkers);

membatalkan prepareImage (cv const :: Mat & bgraMat,


cv :: Mat & grayscale);

membatalkan performThreshold (const cv :: Mat & grayscale,


cv :: Mat & thresholdImg);

kekosongan findContours (const cv :: Mat & thresholdImg, std ::


vector <std :: vector <cv :: Point>> & kontur,
int minContourPointsAllowed);

kekosongan findMarkerCandidates (const std :: vector <std :: vector <cv ::


Point>
> &
kontur, std :: vector <Marker> & detectedMarkers);

kekosongan detectMarkers (const cv :: Mat & grayscale,


std :: vector <Marker> & detectedMarkers);

kekosongan estimatePosition (std :: vector <Marker> & detectedMarkers);

pribadi:
};

[ 63 ]

www.it-ebooks.info
Augmented Reality penanda berbasis pada iPhone atau iPad

Untuk membantu Anda lebih memahami penanda deteksi rutin, pengolahan


langkah-demi-langkah pada satu frame dari video akan ditampilkan. Sebuah
sumber gambar yang diambil dari kamera iPad akan digunakan sebagai contoh:

identifikasi penanda
Berikut adalah alur kerja rutin deteksi marker:

1. Mengkonversi gambar masukan ke grayscale.


2. Melakukan operasi threshold biner.
3. Mendeteksi kontur.
4. Mencari kemungkinan spidol.
5. Mendeteksi dan decode spidol.
6. Perkiraan penanda 3D berpose.

konversi grayscale
Konversi ke grayscale diperlukan karena spidol biasanya hanya berisi blok
hitam dan putih dan itu jauh lebih mudah untuk beroperasi dengan mereka
gambar grayscale. Untungnya, OpenCV konversi warna cukup sederhana.
Silakan lihat di kode berikut listing di C ++:
membatalkan MarkerDetector :: prepareImage (const cv ::
Mat & bgraMat, cv :: Mat & grayscale)
{
// Konversi ke grayscale
cv :: cvtColor (bgraMat, grayscale, CV_BGRA2GRAY);
}

[ 64 ]

www.it-ebooks.info
Bab 2

Fungsi ini akan mengkonversi input BGRA gambar ke grayscale (akan


mengalokasikan buffer gambar jika perlu) dan menempatkan hasilnya ke dalam
argumen kedua. Semua langkah lebih lanjut akan dilakukan dengan gambar
grayscale.

gambar binarization
Operasi binarization akan mengubah setiap piksel dari gambar kita menjadi hitam
(nol intensitas) atau putih (intensitas penuh). Langkah ini diperlukan untuk
menemukan kontur. Ada beberapa metode threshold; masing-masing memiliki sisi
kuat dan lemah. Cara termudah dan tercepat adalah ambang mutlak. Dalam
metode ini nilai yang dihasilkan tergantung pada intensitas pixel saat ini dan
beberapa nilai ambang batas. Jika intensitas pixel lebih besar dari nilai ambang
batas, hasilnya akan menjadi putih (255); jika tidak maka akan menjadi hitam (0).
Metode ini memiliki besar kelemahan-itu tergantung pada kondisi pencahayaan
dan perubahan intensitas ringan. Metode yang lebih disukai adalah ambang
adaptif. Perbedaan utama dari metode ini adalah penggunaan semua piksel dalam
mengingat radius sekitar pixel diperiksa. Menggunakan intensitas rata-rata
memberikan hasil yang baik dan mengamankan deteksi sudut yang lebih kuat.
Potongan kode berikut menunjukkan MarkerDetector fungsi:
membatalkan MarkerDetector :: performThreshold (const cv :: Mat & grayscale,
cv :: Mat & thresholdImg)
{
cv :: adaptiveThreshold
(grayscale, // image Masukan
thresholdImg, // Hasil citra biner
255, //
cv :: ADAPTIVE_THRESH_GAUSSIAN_C,
//
cv :: THRESH_BINARY_INV, //
7, //
7 //
);
}

Setelah menerapkan ambang adaptif terhadap citra masukan, gambar


yang dihasilkan terlihat mirip dengan salah satu berikut:

[ 65 ]
www.it-ebooks.info
Augmented Reality penanda berbasis pada iPhone atau iPad

Setiap penanda biasanya terlihat seperti sosok persegi dengan daerah hitam dan
putih di dalamnya. Jadi cara terbaik untuk menemukan penanda adalah untuk
menemukan kontur tertutup dan perkiraan mereka dengan poligon dari 4 simpul.

deteksi kontur
Itu cv :: findCountours Fungsi akan mendeteksi kontur pada input citra biner:
kekosongan MarkerDetector :: findContours (const cv :: Mat & thresholdImg,
std :: vector <std :: vector <cv ::
Point>
> & Kontur,
int minContourPointsAllowed)
{
std :: vector <std :: vector <cv :: Point>> allContours; cv ::
findContours (thresholdImg, allContours, CV_RETR_LIST, CV_
CHAIN_APPROX_NONE);

contours.clear ();
untuk (size_t i = 0; i <allContours.size (); i ++)
{
int contourSize = allContours [i] .size ();
jika (contourSize> minContourPointsAllowed)
{
contours.push_back (allContours [i]);
}
}
}

Nilai kembali dari fungsi ini adalah daftar poligon di mana masing-masing poligon
merupakan kontur tunggal. Fungsi melompat kontur yang memiliki perimeter mereka
nilai piksel diatur menjadi kurang dari nilaiminContourPointsAllowedvariabel. Hal
ini karena kita tidak tertarik pada kontur kecil. (Mereka mungkin akan tidak
mengandung penanda, atau kontur tidak akan dapat dideteksi karena ukuran
penanda kecil.)

[ 66 ]
www.it-ebooks.info
Bab 2

Gambar berikut ini menunjukkan visualisasi kontur terdeteksi:

calon mencari
Setelah menemukan kontur, tahap poligon pendekatan dilakukan. Hal ini
dilakukan untuk mengurangi jumlah poin yang menggambarkan bentuk kontur.
Ini adalah kualitas cek baik untuk menyaring daerah tanpa penanda karena
mereka selalu bisa diwakili dengan poligon yang berisi empat simpul. Jika poligon
didekati memiliki lebih dari atau kurang dari 4 simpul, itu jelas bukan apa yang
kita cari. Kode berikut mengimplementasikan ide ini:
kekosongan MarkerDetector :: findCandidates
(
const ContoursVector & kontur,
std :: vector <Marker> & detectedMarkers
)
{
std :: vector <cv :: Point> approxCurve;
std :: vector <Marker> possibleMarkers;

Untuk setiap kontur, menganalisis jika itu adalah kemungkinan


parallelepiped untuk
menjadi
penanda
untuk (size_t i = 0; i <contours.size (); i ++)
{
// Perkiraan untuk poligon ganda
eps = kontur [i] .size () * 0,05;

[ 67 ]
www.it-ebooks.info
Augmented Reality penanda berbasis pada iPhone atau iPad

cv :: approxPolyDP (kontur [i], approxCurve, eps, true);

// Kami hanya tertarik pada poligon yang hanya berisi empat


poin
jika (approxCurve.size ()! = 4)
terus;

// Dan mereka harus cembung


if (! cv :: isContourConvex (approxCurve))
terus;

Pastikan bahwa jarak antara titik berurutan besar


cukup
mengapung minDist = std :: numeric_limits <mengapung> :: max ();

for (int i = 0; i <4; i ++)


{
cv :: Titik sisi = approxCurve [i] - approxCurve [(i +
1)% 4]; mengapung squaredSideLength = side.dot (sisi);
minDist = std :: min (minDist, squaredSideLength);
}

bahw jarak ak tid sang kecil ji (minDist <


Memer a u ak at ka
iksa s
m_minContourLengthAllowed)
terus;

Semua tes berlalu. Simpan calon penanda: Marker m;

for (int i = 0; i <4; i ++)


m.points.push_back (cv :: Point2f (approxCurve [i] .x, approxCu
rve [i] .v));

Mengurutkan poin dalam rangka anti-searah jarum jam


Melacak garis antara titik pertama dan kedua.
Jika titik ketiga adalah di sisi kanan, maka poin
adalah anti
searah jarum jam
cv :: Titik v1 = m.points [1] - m.points [0];
cv :: Titik v2 = m.points [2] - m.points [0];

ganda o = (v1.x * v2.y) - (v1.y * v2.x);

if (o <0,0) // jika titik ketiga adalah di sisi kiri,


kemudian

[ 68 ]
www.it-ebooks.info

Anda mungkin juga menyukai