Berkenalan dengan Pillow - Library untuk Pengolahan Citra dalam Python

Photo by C M on Unsplash

Berkenalan dengan Pillow - Library untuk Pengolahan Citra dalam Python

Modul PIL atau Pillow banyak digunakan untuk keperluan pengolahan citra. Dalam artikel ini akan dibahas beberapa fitur dasar penggunaannya.

Bahasa pemrograman Python memiliki ribuan paket modul (library) yang dapat Anda gunakan untuk melakukan banyak hal. Terdapat modul yang khusus dimanfaatkan untuk mengolah citra atau gambar, mulai dari sekadar menampilkan gambar, membaca nilai piksel gambar dan mengubah gambar berwarna menjadi warna abu-abu (grayscale) atau warna lain, mengubah ukuran gambar, mengubah format gambar disertai pengubahan kualitasnya, mengekstraksi fitur, hingga tingkat lebih tinggi seperti mendeteksi obyek dan lain sebagainya.

Ada banyak paket (modul) populer untuk bekerja dengan gambar dalam Python, seperti scikit-image, OpenCV, NumPy, Pillow (PIL), dan lain sebagainya. Dalam artikel ini akan disajikan tutorial pendahuluan dalam menggunakan modul Pillow sering disebut PIL, yang kepanjangan dari Python Imaging LIbrary. Panduan lengkap penggunaan PIL dapat Anda temukan di laman web Pillow ReadTheDocs.

1. Instalasi

Jika Anda belum memasang modul PIL di lingkungan pengembangan Python, maka Anda dapat melakukan pemasangan terlebih dahulu. Berikut ini perintahnya.

python3 -m pip install --upgrade pip
python3 -m pip install --upgrade Pillow

Saat artikel ini ditulis, saya menggunakan Python 3.9 dan Pillow 8.4.0.

2. Menampilkan Gambar

Dalam bagian ini akan saya demokan cara menampilkan gambar dengan 3 cara berbeda. Terdapat 3 urutan utama yang yang harus dilakukan, yaitu (1) impor metode atau fungsi Image pada modul PIL, (2) memuatkan fail gambar pada sebuah variabel, dan (3) menampilkan isi variabel (data gambar) ke layar.

Gambar yang saya gunakan diambil dari Unsplash@sharonp.

from PIL import Image
gambar = Image.open('sharon-pittaway-iMdsjoiftZo-unsplash.jpg')

Anda juga dapat meletakkan nama fail gambar dalam sebuah variabel.

from PIL import Image
nama_fail = 'sharon-pittaway-iMdsjoiftZo-unsplash.jpg'
gambar = Image.open(nama_fail)

Penulisan nama fail yang disertai alamat jalur (path) lengkap sebaiknya disertai karakter "r" yang berarti "raw string". Hal ini umum digunakan untuk menghindari pembacaan karakter tertentu yang dianggap sebagai bagian dari kode (perintah) dalam Python. Contoh penggunaannya adalah sebagai berikut.

gambar = Image.open(r'D:\PythonKu\computer_vision\pil_tuts\sharon-pittaway-iMdsjoiftZo-unsplash.jpg')

Berikutnya adalah cara menampilkan isi variabel ke layar.

a) Menggunakan perintah show.

gambar.show()

Perintah ini akan membuka gambar pada perangkat lunak penampil gambar bawaan (default) di sistem operasi Anda. Kode ini memiliki perilaku yang sama ketika dijalankan di PyCharm, Visual Studio, dan Jupyter Notebook. Khusus untuk PyCharm, di bagian console ternyata menampilkan pesan kesalahan seperti pada gambar ini.

image.png Untuk menanganinya adalah dengan menambahkan perintah import pylab di bagian atas.

b) Menampikan via modul matplotlib.

Jika Anda sudah memasang modul matplotlib, caranya adalah sebagai berikut.

from matplotlib import pyplot as plt
# . . .
plt.imshow(gambar)
plt.show()

Luaran gambar adalah sebagai berikut.

image.png

Jika Anda ingin menghilangkan tampilan sumbu horizontal dan vertikalnya, tambahkan perintah plt.axis(False) sebelum menampilkan gambar.

c) Menggunakan perintah Display. Perintah display dapat digunakan khusus dalam Jupyter Notebook. Gambar akan ditampilkan di bagian bawah sel kode.

display(gambar)

image.png

3. Menampilkan Informasi Gambar

Beberapa informasi gambar yang dapat Anda lihat adalah ukuran (lebar dan tinggi), mode, format, dan lain-lain. Berikut ini contohnya.

ukuran = gambar.size
print(f'Ukuran gambar: {ukuran}')
lebar, tinggi = ukuran
print(f'Lebar: {lebar}, Panjang: {tinggi}')
print(f'Mode: {gambar.mode}')
print(f'Nama fail: {gambar.filename}')
print(f'Format: {gambar.format}')
print(f'Deskripsi format: {gambar.format_description}')

Contoh luarannya adalah:

Ukuran gambar: (640, 640)
Lebar: 640, Panjang: 640
Mode: RGB
Nama fail: sharon-pittaway-iMdsjoiftZo-unsplash.jpg
Format: JPEG
Deskripsi format: JPEG (ISO 10918)

4. Membaca Nilai Warna (Piksel)

Dalam mode RGB (Red, Green, Blue), setiap piksel akan mengandung 3 buah nilai warna merah (red), hijau (green), dan biru (blue). Sebagai pengingat, bawah kombinasi nilai (0, 0, 0) adalah warna hitam, nilai (255, 255, 255) adalah warna putih, nilai (255, 0, 0) warna merah, nilai (0, 255, 0) warna hijau, nilai (0, 0, 255) warna biru, dan seterusnya.

Perintah utama untuk membaca nilai warna (piksel) pada gambar adalah dengan menggunakan perintah getpixel((i, j)), di mana variabel i menunjukkan baris, dan j adalah kolom.

Jadi, yang kita lakukan berikutnya adalah membaca piksel untuk setiap baris dan kolom dari gambar. Dikarenakan ukuran gambar adalah 640x640, di mana terdapat 640 baris dan 640 kolom, maka akan mengeluarkan 25.600 nilai RGB. Berikut adalah contoh kodenya.

from PIL import Image

gambar = Image.open('sharon-pittaway-iMdsjoiftZo-unsplash.jpg')
lebar, tinggi = gambar.size
for i in range(lebar):
    for j in range(tinggi):
        nilai_piksel = gambar.getpixel((i, j))
        print(nilai_piksel)

Contoh sebagian isi piksel ada pada gambar berikut.

image.png

5. Modifikasi Nilai Piksel

Setelah berhasil membaca nilai warna setiap piksel pada gambar, berikutnya kita dapat melakukan manipulasi atau modifikasi nilai sesuai keinginan. Berikut ini akan saya contohkan mengubah nilai warna yang tadinya berwarna (RGB) menjadi warna abu-abu.

Rumus untuk mendapatkan warna abu-abu adalah sebagai berikut.

nilai_abu = (0.299 x red) + (0.587 x green) + (0.114 x blue)

Jadi, nilai warna abu-abu hasil penghitungan rumus di atas akan disimpan di tiga kolom RGB, yang berarti:

nilai_baru = ( int(nilai_abu), int(nilai_abu), int(nilai_abu) )

Fungsi int digunakan untuk memastikan nilai_abu tetap dalam format bilangan genap atau integer. Berikut ini adalah kodenya.

from PIL import Image

gambar = Image.open('sharon-pittaway-iMdsjoiftZo-unsplash.jpg')
lebar, tinggi = gambar.size

# masukkan isi piksel ke dalam daftar_piksel_gambar - format baris x kolom - tuple RGB
daftar_piksel_gambar = gambar.load()

for i in range(lebar):
    for j in range(tinggi):
        # baca piksel dalam format RGB
        r, g, b = gambar.getpixel((i, j))
        # setiap nilai di kolom RGB diubah ke warna keabuan sesuai rumus
        nilai_abu = (0.299*r + 0.587*g + 0.114*g)
        # masukkan warna baru keabuan dalam tuple
        daftar_piksel_gambar[i, j] = (int(nilai_abu), int(nilai_abu), int(nilai_abu))

fail_abu = "gambar_abu-abu.jpg"
# simpan gambar abu-abu ke fail baru
gambar.save(fail_abu)
# tampilkan gambar abu-abu
gambar_abu = Image.open(rf'{fail_abu}')
display(gambar_abu)
# gambar_abu.show()

Contoh luarannya adalah:

image.png

Jika Anda tidak menggunakan Jupyter Notebook, gunakan cara penampilan gambar (a) atau (b) pada bahasan nomor 1 sebelumnya.

Cara cepat atau instan adalah dengan mengonversi gambar dari mode 'RGB' ke 'L' (luminance), yang berarti hanya terdiri dari 1 kanal warna saja. Rumus untuk mendapat nilai dalam mode L adalah sebagai berikut [laman web Pillow].

L = R 299/1000 + G 587/1000 + B * 114/1000

6. Mengonversi Gambar ke Hitam Putih

Melanjutkan penjelasan konversi gambar berwarna ke format abu-abu cara instan sebelumnya, yaitu dengan cara menyesuaikan kanal 3 warna (RGB) menjadi 1 warna (L). Kodenya adalah sebagai berikut.

from PIL import Image

gambar = Image.open('sharon-pittaway-iMdsjoiftZo-unsplash.jpg')
gambar_abu = gambar.convert('L')
# gambar_abu.show()
display(gambar_abu)

Hasil dari kode tersebut di atas sama dengan cara manipulasi nilai piksel secara manual pada penjelasan di nomor 5 sebelumnya. Hanya saja, nilai piksel hanya berupa satu nilai mulai dari 0 (menunjukkan warna hitam) s/d 255 (menunjukkan warna putih).

Berikutnya, kita akan membuat gambar yang benar-benar hanya berisi warna hitam atau putih, yaitu 0 atau 255. Kita buat dulu batas ambangnya adalah setengah nilai dari 255, misalnya 128. Jika ada nilai piksel yang di bawah 128, maka kita anggap berwarna hitam (nilai 0). Sebaliknya, jika nilainya lebih besar atau sama dengan 128, maka kita anggap putih (nilai 255). Kodenya adalah sebagai berikut.

from PIL import Image

gambar = Image.open('sharon-pittaway-iMdsjoiftZo-unsplash.jpg')
gambar_abu = gambar.convert('L')
daftar_piksel_gambar = gambar_abu.load()
batas = 128

for i in range(gambar_abu.size[0]):
    for j in range(gambar_abu.size[1]):
        if gambar_abu.getpixel((i, j)) < 128:
            nilai_baru = 0
        else:
            nilai_baru = 255
        daftar_piksel_gambar[i, j] = nilai_baru

fail_hp = "gambar_hitam_putih.jpg"
gambar_abu.save(fail_hp)
gambar_hp = Image.open(fail_hp)
display(gambar_hp)
# gambar_hp.show()

Setelah dilakukan pengubahan nilai piksel, dari daftar piksel gambar selanjutnya disimpan dalam sebuah fail gambar baru yang disimpan dalam variabel fail_hp. Luarannya adalah sebagai berikut.

image.png

Cara lain yang sedikit lebih pendek adalah sebagai berikut.

gambar_hitam_putih = gambar_abu.point(lambda x: 0 if x<128 else 255, '1')
gambar_hitam_putih.save("gambar_hitam_putih.jpg")
display(gambar_hitam_putih)

Penentuan nilai piksel dapat dilakukan melalui fungsi .poin di mana di dalamnya disertai fungsi lambda yang bertugas menyeleksi jika suatu nilai di bawah atau di atas batas ambang yang ditentukan, dalam hal ini nilai 128. Langkah berikutnya sama dengan kode sebelumnya, yaitu menyimpan data piksel ke dalam gambar baru.

Selanjutnya, Anda dapat bereksperimen dengan penentuan batas ambang yang berbeda untuk mendapatkan porsi warna hitam dan putih yang lebih sesuai.

Kode sumber dalam format Jupyter Notebook tersedia di repositori.


Untuk sementara sampai di sini pembahasan pengenalan modul PIL dalam Python. Di artikel berikutnya akan kita bahas lebih banyak lagi hal-hal yang bisa kita lakukan untuk pengolahan citra dan contoh nyatanya.

Semoga bermanfaat.