Saat sebuah jendela perhitungan — filter citra, rata-rata bergerak — berjalan di dekat tepi data, jendela tersebut membutuhkan tetangga yang tidak tersedia. Tanpa penanganan khusus, hasil perhitungan lebih pendek daripada data asli, atau kode harus menulis cabang khusus untuk tiap tepi. np.pad menyelesaikan masalah ini dengan menambahkan lapisan baru di sekeliling array sehingga semua posisi memiliki tetangga.

Sebagai bahan latihan, kita memakai citra abu-abu kecil 3x3 dengan nilai 0-255 yang disederhanakan menjadi angka puluhan. Empat mode yang dibahas:

  • constant: tepi diisi nilai tetap (default 0).
  • edge: piksel tepi terdekat disalin.
  • reflect: isi array dicerminkan; piksel tepi tidak digandakan.
  • wrap: tepi diambil dari sisi berlawanan.

Mode constant dan Bentuk pad_width #

Signature lengkapnya adalah np.pad(array, pad_width, mode='constant', **kwargs). Argumen pad_width menerima tuple (sebelum, sesudah) per axis; sebuah bilangan tunggal diterapkan ke semua axis.

python
import numpy as np

citra = np.array([[10, 20, 30],
                  [40, 50, 60],
                  [70, 80, 90]])
print(np.pad(citra, ((1, 1), (1, 1)), mode="constant"))
print(np.pad(citra, ((2, 0), (0, 1)), mode="constant", constant_values=255))

Output yang Dihasilkan:

text
[[ 0  0  0  0  0]
 [ 0 10 20 30  0]
 [ 0 40 50 60  0]
 [ 0 70 80 90  0]
 [ 0  0  0  0  0]]
[[255 255 255 255]
 [255 255 255 255]
 [ 10  20  30 255]
 [ 40  50  60 255]
 [ 70  80  90 255]]

Mari kita bedah:

  1. Baris 3-5: citra abu-abu 3x3 yang menjadi bahan latihan sepanjang bab.
  2. Baris 6: ((1, 1), (1, 1)) berarti satu lapisan sebelum dan sesudah tiap axis; bentuk hasil menjadi (5, 5) dan tepi diisi 0 (hitam) sesuai default mode constant.
  3. Baris 7: pad_width boleh asimetris — 2 baris di atas, 0 baris di bawah, 0 kolom di kiri, 1 kolom di kanan; constant_values=255 mengisi tepi dengan putih.

Perhitungan bentuknya sederhana: tiap axis bertambah sebesar jumlah lapisan sebelum dan sesudahnya. Aturan kecocokan ukuran ketika menata ulang array dibahas pada Chapter Memeriksa Kompatibilitas Bentuk.

Mode edge: Piksel Tepi Disalin #

Mode edge mengisi lapisan baru dengan menyalin piksel tepi terdekat, seolah baris dan kolom pinggir diperpanjang.

python
import numpy as np

citra = np.array([[10, 20, 30],
                  [40, 50, 60],
                  [70, 80, 90]])
print(np.pad(citra, 1, mode="edge"))

Output yang Dihasilkan:

text
[[10 10 20 30 30]
 [10 10 20 30 30]
 [40 40 50 60 60]
 [70 70 80 90 90]
 [70 70 80 90 90]]

Perhatikan polanya: baris pertama dan terakhir hasil adalah salinan baris tepi asli, dan hal yang sama terjadi pada kolom. Bagi operasi rata-rata di tepi, mode ini membuat nilai pinggir tetap diperhitungkan — bukan digantikan nol.

Mode reflect dan wrap #

Mode reflect mencerminkan isi array; piksel tepi asli tidak digandakan di luar posisinya. Mode wrap memperlakukan array sebagai bidang menyambung: tepi kanan bersambung ke tepi kiri, tepi bawah ke tepi atas.

python
import numpy as np

citra = np.array([[10, 20, 30],
                  [40, 50, 60],
                  [70, 80, 90]])
print(np.pad(citra, 1, mode="reflect"))

Output yang Dihasilkan:

text
[[50 40 50 60 50]
 [20 10 20 30 20]
 [50 40 50 60 50]
 [80 70 80 90 80]
 [50 40 50 60 50]]

Baris paling atas hasil adalah cermin baris kedua (40, 50, 60), dengan pojoknya ikut tercermin. Untuk kebutuhan sejenis NumPy juga menyediakan mode symmetric, yang membedakan pada satu hal: tepi ikut digandakan. Jangan tertukar antara keduanya saat membaca kode orang lain.

python
import numpy as np

citra = np.array([[10, 20, 30],
                  [40, 50, 60],
                  [70, 80, 90]])
print(np.pad(citra, 1, mode="wrap"))

Output yang Dihasilkan:

text
[[90 70 80 90 70]
 [30 10 20 30 10]
 [60 40 50 60 40]
 [90 70 80 90 70]
 [30 10 20 30 10]]

Pojok kiri atas hasil berisi 90 — nilai dari pojok kanan bawah. Array terbaca menyambung melingkar, cocok untuk data berpola berulang seperti tekstur.

Kasus: Menyiapkan Tepi untuk Jendela Bergerak #

Rata-rata bergerak 3 titik pada sinyal 5 titik hanya menghasilkan 3 nilai bila dihitung tanpa tambahan tepi. Dengan padding edge terlebih dulu, jendela dapat berjalan penuh dan hasilnya tetap 5 nilai. Fungsi sliding_window_view dipakai di sini sekilas; cara kerjanya dibahas tuntas pada Chapter Strides dan Memory Access.

python
import numpy as np

sinyal = np.array([5, 12, 8, 20, 3])
dilapisi = np.pad(sinyal, 1, mode="edge")
print(dilapisi)
jendela = np.lib.stride_tricks.sliding_window_view(dilapisi, 3)
print(jendela.shape)
print(jendela[0])
print(jendela.mean(axis=1).round(2))

Output yang Dihasilkan:

text
[ 5  5 12  8 20  3  3]
(5, 3)
[ 5  5 12]
[ 7.33  8.33 13.33 10.33  8.67]
  1. Baris 4-5: mode edge menambah satu titik di tiap ujung; nilai pertama dan terakhir sinyal disalin, panjang berubah dari 5 menjadi 7.
  2. Baris 6-7: sliding_window_view(dilapisi, 3) menyusun semua jendela 3 titik tanpa menyalin data — bentuknya (5, 3), satu baris per posisi jendela.
  3. Baris 8: jendela pertama adalah [5 5 12], tepat berasal dari titik tepi hasil padding.
  4. Baris 9: rata-rata tiap baris memberi 5 nilai, sama dengan panjang sinyal asli.

Perhatian Memori: pad Menyalin Data #

np.pad selalu mengembalikan array baru yang berisi salinan seluruh data asli ditambah tepinya; fungsi tersebut tidak pernah mengembalikan view. Untuk array besar, tiap panggilan mengalokasikan memori seukuran array hasil. Bila padding dilakukan berulang — misalnya per frame video — pertimbangkan menyiapkan buffer besar sekali lalu menyalin data ke tengahnya, atau menghitung tepi secara manual di dalam perulangan.

Tabel berikut merangkum keempat mode:

ModeNilai tepi baruCocok untuk
constantnilai tetap, default 0bingkai hitam atau putih, nilai netral
edgepiksel tepi terdekat disalinrata-rata bergerak di ujung sinyal
reflectcermin isi, tepi tidak digandakanfilter citra
wrapsisi berlawananpola berulang seperti tekstur