Table of Contents

Menggunakan EasyAR di dalam mesin 3D

Untuk menggunakan EasyAR dalam mesin 3D, perlu merender aliran kamera dan objek virtual. Merender objek virtual membutuhkan keselarasan dengan aliran kamera. Saat merender aliran kamera, beberapa parameter saat gambar dihasilkan dan saat ditampilkan mungkin tidak cocok, seperti posisi, orientasi, format, rasio aspek kamera fisik yang mungkin berbeda dari tampilan layar, dan ini perlu dipertimbangkan saat rendering. Jika perlu menyambungkan EasyAR ke mesin 3D yang tidak didukung, perhatikan detail berikut dengan seksama.

Pemangkasan untuk padding batas aliran kamera

Pemangkasan gambar, transposisi, dan encoding memerlukan perhitungan yang besar. Untuk mengurangi perhitungan dan latensi, format yang lebih mentah biasanya digunakan. Untuk memudahkan encoding video, gambar yang dihasilkan oleh kamera fisik sering kali disejajarkan ke dalam grid 8x8, 16x16, 32x32, 64x64. Misalnya, di beberapa ponsel dengan resolusi 1920x1080, gambar keluaran mungkin menjadi 1920x1088 karena 1080 bukan kelipatan 64.

image with padding

Ini mengharuskan bagian padding yang berlebih dihilangkan saat rendering. Ada beberapa cara yang mungkin: satu adalah dengan menentukan lebar saat mengunggah gambar ke memori video, misalnya di OpenGL dapat menggunakan glPixelStorei(GL_PACK_ROW_LENGTH, ...); yang lain adalah menghitung koordinat UV secara manual dalam fragment shader, dan memotong bagian yang melebihi saat mengambil sampel dari gambar.

Merender mengikuti orientasi rotasi layar

Di ponsel, gambar yang direkam oleh kamera fisik biasanya tetap relatif terhadap bodi perangkat, tidak berubah dengan orientasi tampilan layar. Namun, perubahan orientasi bodi ponsel memengaruhi definisi arah atas, bawah, kiri, dan kanan gambar. Saat rendering, orientasi tampilan layar saat ini juga memengaruhi arah gambar yang ditampilkan.

Biasanya saat rendering, sudut rotasi gambar kamera relatif terhadap orientasi tampilan layar perlu ditentukan.

Jika kita menggunakan \(\theta_{screen}\) untuk menunjukkan radian rotasi searah jarum jam gambar layar relatif terhadap orientasi alami layar, \(\theta_{phycam}\) untuk menunjukkan radian rotasi searah jarum jam yang dibutuhkan gambar kamera fisik agar ditampilkan dengan benar pada layar berorientasi alami, dan \(\theta\) untuk menunjukkan radian rotasi searah jarum jam yang dibutuhkan gambar kamera fisik untuk ditampilkan pada layar saat ini.

Untuk kamera belakang, berlaku

\[ \theta = \theta_{phycam} - \theta_{screen} \]

Misalnya, di ponsel Android, saat digunakan dalam orientasi alami, \(\theta_{screen} = 0, \theta_{phycam} = \frac{\pi}{2}\), maka \(\theta = \frac{\pi}{2}\).

Untuk kamera depan, jika setelah rotasi selesai, dilakukan flip kiri-kanan, maka berlaku

\[ \theta = \theta_{phycam} + \theta_{screen} \]
Catatan

Saat gambar layar berotasi, \(\theta\) perlu dihitung ulang segera pada frame pertama setelah rotasi terjadi, jika tidak, orientasi gambar layar yang tidak normal mungkin muncul sesaat.

Rendering latar belakang kamera dan objek virtual

Merender objek virtual di ponsel memerlukan penyelarasan objek virtual dengan aliran kamera. Ini mengharuskan kita menempatkan kamera render dan objek dalam ruang virtual yang sepenuhnya sesuai dengan ruang nyata, dan melakukan rendering menggunakan sudut pandang (field of view) dan rasio aspek yang sama dengan kamera fisik. Transformasi proyeksi perspektif yang dialami oleh aliran kamera dan objek virtual hampir identik, dengan satu perbedaan utama: sebagian besar transformasi proyeksi perspektif untuk aliran kamera terjadi di dalam kamera fisik, sedangkan untuk objek virtual sepenuhnya merupakan proses komputasi.

Berikut mengikuti konvensi OpenGL. Dengan konvensi lain, pemetaan sumbu koordinat yang sesuai perlu dilakukan. Asumsikan sistem koordinat kamera didefinisikan sebagai: sumbu x mengarah ke kanan, sumbu y mengarah ke atas, sumbu z mengarah keluar dari layar. Sistem koordinat kliping didefinisikan sebagai: sumbu x mengarah ke kanan, sumbu y mengarah ke atas, sumbu z mengarah keluar dari layar, sumbu w adalah sumbu virtual.

Dalam hal ini, matriks transformasi proyeksi perspektif yang diperlukan untuk merender aliran kamera adalah:

\[ P_i=\left( \begin{array}{cccc} (-1)^{\text{flip}} & \phantom{0} & \phantom{0} & \phantom{0} \\ \phantom{0} & 1 & \phantom{0} & \phantom{0} \\ \phantom{0} & \phantom{0} & 1 & \phantom{0} \\ \phantom{0} & \phantom{0} & \phantom{0} & 1 \\ \end{array} \right)\left( \begin{array}{cccc} \cos (-\theta ) & -\sin (-\theta ) & \phantom{0} & \phantom{0} \\ \sin (-\theta ) & \cos (-\theta ) & \phantom{0} & \phantom{0} \\ \phantom{0} & \phantom{0} & 1 & \phantom{0} \\ \phantom{0} & \phantom{0} & \phantom{0} & 1 \\ \end{array} \right)\left( \begin{array}{cccc} s_x & \phantom{0} & \phantom{0} & \phantom{0} \\ \phantom{0} & s_y & \phantom{0} & \phantom{0} \\ \phantom{0} & \phantom{0} & 1 & \phantom{0} \\ \phantom{0} & \phantom{0} & \phantom{0} & 1 \\ \end{array} \right) \]

Dimana: flip mengindikasikan apakah gambar diflip kiri-kanan, bernilai 1 jika ya, 0 jika tidak; \(\theta\) adalah sudut rotasi gambar searah jarum jam dalam radian; \(s_x\), \(s_y\) adalah faktor skala untuk penskalaan isotropik atau padding isotropik, nilainya bervariasi dengan \(\theta\). Matriks transformasi ini pertama-tama menskalakan gambar kamera, kemudian merotasinya, dan terakhir melakukan flip jika diperlukan. Saat rendering, sebuah persegi panjang yang menutupi seluruh layar harus digunakan, misalnya di OpenGL, titik sudut persegi panjang dapat diletakkan di \((-1, -1, 0)\), \((1, -1, 0)\), \((1, 1, 0)\), \((-1, 1, 0)\), dengan koordinat UV diatur di empat sudut yang sesuai, kemudian menggunakan matriks proyeksi perspektif ini untuk merender.

Matriks proyeksi perspektif yang diperlukan untuk merender objek virtual adalah:

\[ P=P_i\left( \begin{array}{cccc} 1 & \phantom{0} & \phantom{0} & \phantom{0} \\ \phantom{0} & 1 & \phantom{0} & \phantom{0} \\ \phantom{0} & \phantom{0} & -\frac{f+n}{f-n} & -\frac{2 f n}{f-n} \\ \phantom{0} & \phantom{0} & -1 & \phantom{0} \\ \end{array} \right)\left( \begin{array}{cccc} \frac{2}{w} & \phantom{0} & \phantom{0} & \phantom{0} \\ \phantom{0} & \frac{2}{h} & \phantom{0} & \phantom{0} \\ \phantom{0} & \phantom{0} & 1 & \phantom{0} \\ \phantom{0} & \phantom{0} & \phantom{0} & 1 \\ \end{array} \right)\left( \begin{array}{cccc} 1 & \phantom{0} & \phantom{0} & \phantom{0} \\ \phantom{0} & -1 & \phantom{0} & \phantom{0} \\ \phantom{0} & \phantom{0} & -1 & \phantom{0} \\ \phantom{0} & \phantom{0} & \phantom{0} & 1 \\ \end{array} \right)\left( \begin{array}{cccc} f_x & \phantom{0} & c_x & \phantom{0} \\ \phantom{0} & f_y & c_y & \phantom{0} \\ \phantom{0} & \phantom{0} & 1 & \phantom{0} \\ \phantom{0} & \phantom{0} & \phantom{0} & 1 \\ \end{array} \right)\left( \begin{array}{cccc} 1 & \phantom{0} & \phantom{0} & \phantom{0} \\ \phantom{0} & -1 & \phantom{0} & \phantom{0} \\ \phantom{0} & \phantom{0} & -1 & \phantom{0} \\ \phantom{0} & \phantom{0} & \phantom{0} & 1 \\ \end{array} \right) \]

Dimana: \(n\), \(f\) adalah parameter kliping dekat dan jauh yang digunakan dalam matriks proyeksi perspektif rendering 3D biasa; \(w\), \(h\) adalah lebar dan tinggi piksel gambar kamera; \(f_x\), \(f_y\), \(c_x\), \(c_y\) adalah parameter intrinsik kamera yang umum digunakan dalam model kamera, dengan \(f_x\), \(f_y\) sebagai panjang fokus piksel, \(c_x\), \(c_y\) sebagai posisi piksel titik utama. Matriks proyeksi ini secara berurutan melakukan transformasi berikut: transformasi proyeksi perspektif parameter intrinsik kamera (karena arah sumbu y dan z dalam sistem koordinat gambar OpenCV berlawanan dengan sistem koordinat kamera OpenGL, dilakukan dua kali transformasi sistem koordinat), transformasi dari sistem koordinat piksel gambar ke sistem koordinat persegi panjang gambar, transformasi kliping dekat dan jauh, dan transformasi proyeksi perspektif yang sama seperti saat merender aliran kamera.

Setelah disederhanakan, diperoleh:

\[ P=P_i\left( \begin{array}{cccc} \frac{2 f_x}{w} & \phantom{0} & 1-\frac{2 c_x}{w} & \phantom{0} \\ \phantom{0} & \frac{2 f_y}{h} & -1+\frac{2 c_y}{h} & \phantom{0} \\ \phantom{0} & \phantom{0} & -\frac{f+n}{f-n} & -\frac{2 f n}{f-n} \\ \phantom{0} & \phantom{0} & -1 & \phantom{0} \\ \end{array} \right) \]

Dari proses di atas, terlihat bahwa rendering biasanya perlu dilakukan dalam dua tahap: satu kali untuk merender aliran kamera, dan satu kali untuk merender objek virtual, dengan objek virtual menutupi aliran kamera.

Beberapa mesin 3D menyatakan matriks proyeksi perspektif dalam parameter seperti sudut pandang horizontal (horizontal field of view), rasio aspek, dll. Jika rotasi dan flip diabaikan, dan offset titik utama diabaikan, parameter ini dapat dihitung, dengan sudut pandang horizontal \(\alpha=2 \arctan{\frac{w}{2 f_x}}\), dan rasio aspek \(r=\frac{w}{h}\).

Perlu diperhatikan bahwa proses ini tidak memperhitungkan distorsi kamera, karena distorsi kamera pada sebagian besar ponsel saat ini sangat minimal.