Assalamualaikum sahabat whitecyber semua, kali ini whitecyber team mendapatkan order untuk membuat program homography.
Yuk kita bahas …
Homography adalah isomorfisme dari ruang proyektif yang diinduksi oleh isomorfisme dari ruang vektor dari mana ruang proyektif berasal. Dalam bidang visi komputer, dua gambar permukaan datar yang sama dalam ruang terkait oleh homografi (dengan asumsi model kamera lubang jarum). Ini memiliki banyak aplikasi praktis, seperti rektifikasi gambar, registrasi gambar, atau gerakan kamera – rotasi dan translasi – antara dua gambar.
.
Memutar gambar bukanlah hal baru, kebanyakan orang yang telah melakukan pengeditan foto dasar sekalipun harus melakukan ini di beberapa titik. Dalam artikel ini, kami akan membahas cara menyesuaikan gambar agar tampak diambil dari sudut yang berbeda.
Projects :
- Bahasa Pemprograman : Python
- File Type : PNG
- Environtment : Visual Studio Code
- Resource : https://github.com/whitecyber-faris/project-ai-2
Seperti biasa, mulailah dengan mengimpor pustaka Python yang diperlukan.
Code :
import matplotlib.pyplot as plt
import numpy as np
from matplotlib.patches import Circle
from skimage import transform
from skimage.io import imread, imshow
.
Luar biasa, sekarang mari kita impor gambar yang akan kita kerjakan.
Code :
sign = imread('words_of_wisdom.png')
plt.figure(num=None, figsize=(8, 6), dpi=80)
.
.
Seperti yang bisa kita lihat, tanda di atas sedikit terbuka. Meskipun saya sengaja mengambil foto itu dari perspektif itu, mari kita lihat apakah kita bisa “memperbaikinya”. Cara paling mendasar untuk melakukannya adalah melalui fungsi transform.rotate di Skimage. Kode di bawah melakukan hal itu.
Code :
sign_rotate = transform.rotate(sign, 330)
plt.figure(num=None, figsize=(8, 6), dpi=80)
imshow(sign_rotate);
.
.
Seperti yang kita lihat, gambar telah diputar sehingga tandanya sekarang sejajar dengan sumbu x. Namun, kami melihat dua masalah yang sangat mencolok.
Yang pertama adalah ini pada dasarnya hanya memutar gambar (kejutan besar bukan?). Yang kedua adalah sekarang ada ruang putih tempat gambar dulu berada. Mari kita coba untuk memperbaiki ini.
Fungsi yang kami gunakan sebenarnya memiliki parameter call mode , ini akan membantu meringankan ruang putih. Mari kita bereksperimen dengan berbagai mode yang bisa kita gunakan.
Code :
def rotate_fills(image):
modes = ['constant', 'edge','symmetric','reflect','wrap']
fig, ax = plt.subplots(3,2, figsize=(7, 10), dpi = 200)
for n, ax in enumerate(ax.flatten()):
n = n-1
if n == -1:
ax.set_title(f'original', fontsize = 12)
ax.imshow(image)
ax.set_axis_off()
else:
ax.set_title(f'{modes[n]}', fontsize = 12)
ax.imshow(transform.rotate(image, 330, mode = modes[n]))
ax.set_axis_off()
fig.tight_layout();
rotate_fills(sign)
.
.
Kita dapat melihat bahwa dengan bereksperimen dengan metode pengisian yang berbeda, yang mencerminkan dan simetris keduanya menonjol sebagai kandidat utama. Namun mereka datang dengan kelemahan yang sangat halus.
Code :
def comparing_fills(image):
modes = ['symmetric','reflect']
fig, ax = plt.subplots(1,2, figsize=(7, 10), dpi = 200)
ax[0].imshow(transform.rotate(image, 330, mode = modes[0]))
ax[0].set_title(f'{modes[0]}', fontsize = 15)
ax[0].set_axis_off()
ax[1].imshow(transform.rotate(image, 330, mode = modes[1]))
ax[1].set_title(f'{modes[1]}', fontsize = 15)
ax[1].set_axis_off()
fig.tight_layout();
comparing_fills(sign)
.
.
Perhatikan bagaimana sudut kanan bawah gambar dipantulkan. Ini membuatnya seolah-olah pohon itu memiliki cabang kedua di sudut itu. Tentu saja saat kami memeriksa gambar aslinya, hal ini tidak terjadi.
Jadi terlepas dari upaya terbaik kami, putar tampaknya bukan fungsi terbaik untuk tugas kami. Untungnya ada fungsi yang bisa kita gunakan yaitu fungsi transform.warp di Skimage.
Namun, itu membutuhkan lebih banyak pekerjaan untuk diterapkan jika dibandingkan dengan rotate . Pertama, kita harus mendapatkan poin yang menjadi perhatian kita dan di mana kita ingin memproyeksikannya. Maafkan kode panjang di bawah ini, tetapi menurut saya penting untuk eksplisit dengan pemrograman sehingga mudah diikuti.
Code :
points_of_interest =[[360, 110],
[420, 270],
[130, 400],
[100, 280]]
projection = [[500, 200],
[500, 390],
[100, 390],
[100, 200]]
color = 'red'
fig, ax = plt.subplots(1,2, figsize=(15, 10), dpi = 80)
patch1 = Circle((points_of_interest[0][0],points_of_interest[0][1]),
10, facecolor = color)
patch2 = Circle((points_of_interest[1][0],points_of_interest[1][1]),
10, facecolor = color)
patch3 = Circle((points_of_interest[2][0],points_of_interest[2][1]),
10, facecolor = color)
patch4 = Circle((points_of_interest[3][0],points_of_interest[3][1]),
10, facecolor = color)
patch5 = Circle((projection[0][0],projection[0][1]), 10,
facecolor = color)
patch6 = Circle((projection[1][0],projection[1][1]), 10,
facecolor = color)
patch7 = Circle((projection[2][0],projection[2][1]), 10,
facecolor = color)
patch8 = Circle((projection[3][0],projection[3][1]), 10,
facecolor = color)
ax[0].add_patch(patch1)
ax[0].add_patch(patch2)
ax[0].add_patch(patch3)
ax[0].add_patch(patch4)
ax[0].imshow(sign);
ax[1].add_patch(patch5)
ax[1].add_patch(patch6)
ax[1].add_patch(patch7)
ax[1].add_patch(patch8)
ax[1].imshow(np.ones((sign.shape[0], sign.shape[1])));
.
.
Apa yang pada dasarnya kami lakukan adalah mengidentifikasi lokasi sudut tanda saat ini dan merencanakan ke mana kami ingin mereka pergi.
Perhatikan bahwa langkah ini hanya untuk memperjelas lokasi sumber dan lokasi tujuan. Untuk benar-benar mengimplementasikan fungsi kita harus menggunakan kode di bawah ini.
Code :
.
points_of_interest = np.array([[360, 110],
[420, 270],
[130, 400],
[100, 280]])
projection = np.array([[500, 200],
[500, 390],
[100, 390],
[100, 200]])
tform = transform.estimate_transform('projective', points_of_interest, projection)
tf_img_warp = transform.warp(sign, tform.inverse, mode = 'symmetric')
plt.figure(num=None, figsize=(8, 6), dpi=80)
fig, ax = plt.subplots(1,2, figsize=(15, 10), dpi = 80)
ax[0].set_title(f'Original', fontsize = 15)
ax[0].imshow(sign)
ax[0].set_axis_off();
ax[1].set_title(f'Transformed', fontsize = 15)
ax[1].imshow(tf_img_warp)
ax[1].set_axis_off();
.
.
Kami melihat bahwa ini merupakan peningkatan yang luar biasa dari metode kami sebelumnya. Tidak hanya sudut tanda telah diperbaiki, tetapi kita tidak lagi harus berurusan dengan masalah ruang putih yang mengganggu.
Namun, perhatikan bahwa meskipun metode ini mengesankan, namun tidak selalu memberikan hasil terbaik. Ambil gambar di bawah ini misalnya.
Code :
.
rumah = imread('artsy_house.png')
plt.angka(num=Tidak ada, figsize=(8, 6), dpi=80)
.
Karena ketebalannya yang mencolok, fungsinya tidak akan memberikan hasil terbaik. Untuk menunjukkan, mari kita plot tempat menarik. Selain itu, saya telah menyediakan cara singkat untuk menjalankan kode sebelumnya
Code :
.
point_of_interest =[[105, 60],
[260, 85],
[275, 295],
[110, 290]]
proyeksi = [[100, 75],
[275, 75],
[275, 290],
[100, 290]]
color = 'green'
patches = []
fig, ax = plt.subplots(1,2, figsize=(15, 10), dpi = 80)
untuk koordinat di (points_of_interest + proyeksi):
patch = Circle((coordinates[0 ],koordinat[1]), 10,
warna wajah = warna)
patch.append(patch)
untuk p di patch[:4]:
ax[0].add_patch(p)
ax[0].imshow(house);
untuk p di patch[4:]:
ax[1].add_patch(p)
ax[1].imshow(np.ones((house.shape[0], house.shape[1])));
.
.
Luar biasa, sekarang mari kita memproyeksikan gambar ke titik target.
Code :
.
poin_kepentingan = np.array(poin_kepentingan)
proyeksi = np.array(proyeksi)
tform = transform.estimate_transform('projective', point_of_interest, proyeksi)
tf_img_warp = transform.warp(house, tform.inverse, mode = 'edge')
plt.figure(num=None, figsize=(8, 6), dpi= 80)
fig, ax = plt.subplots(1,2, figsize=(15, 10), dpi = 80)
ax[0].set_title(f'Original', fontsize = 15)
ax[0].imshow(house)
ax [0].set_axis_off();
ax[1].set_title(f'Transformed', fontsize = 15)
ax[1].imshow(tf_img_warp)
ax[1].set_axis_off();
.
.
Meskipun kami dapat memproyeksikan gambar dengan benar ke titik baru, perhatikan bagaimana tampilannya sedikit tidak alami. Melihat bagian kiri lukisan, kita melihat bagian yang terangkat masih terlihat. Fitur tersebut seharusnya tidak terlihat jika kami benar-benar mengambil bidikan dari sudut depan. Perhatikan juga bagaimana ada sedikit distorsi di bagian kiri atas gambar, hal ini disebabkan oleh penggunaan isian tepi .
Kesimpulan
Kami telah melihat kekuatan menggunakan transform.warp untuk benar-benar mengubah perspektif gambar. Ada banyak cara untuk menerapkan teknik ini, mulai dari survei medan hingga rekreasi gambar. Saya harap Anda sekarang memiliki apresiasi yang lebih baik untuk metode ini dan sekarang dapat membayangkan bagaimana menggunakannya dalam proyek Anda.