Lab Citra Interaktif
Lab Citra

Data Science · Data & Visualisasi

Dari piksel menjadi fitur

Komputer tidak melihat gambar. Ia melihat tabel angka. Presentasi ini menelusuri perjalanan sebuah gambar: bagaimana ia disimpan, direpresentasikan, dibersihkan, lalu diringkas menjadi vektor fitur yang siap dipakai model machine learning.

20 menit · 4 bagian + penutup Semua demo berjalan di browser
1

Bagian 1 · 4 menit

Data gambar

Arahkan kursor atau ketuk gambar untuk memeriksa piksel. Klik untuk mengunci titik.

Gambar digital adalah grid piksel. Setiap piksel menyimpan intensitas cahaya untuk tiga channel warna: merah, hijau, dan biru. Dengan 8 bit per channel, setiap channel punya 256 level (0–255), sehingga satu piksel bisa bernilai salah satu dari 16,7 juta warna.

8 bit

Turunkan bit depth untuk melihat efek kuantisasi: lebih sedikit level berarti lebih sedikit gradasi warna dan ukuran data lebih kecil.

Format penyimpanan: JPG lossy (kompresi membuang detail), PNG lossless, TIFF/DICOM untuk citra ilmiah dan medis. Di memori, semua dibuka menjadi array angka yang sama.

Kode Python: membaca gambar
import cv2
img = cv2.imread("contoh.jpg")          # BGR, uint8
img = cv2.cvtColor(img, cv2.COLOR_BGR2RGB)
print(img.shape, img.dtype)          # (240, 320, 3) uint8
print(img[120, 160])                  # nilai RGB satu piksel

# kuantisasi ke 3 bit per channel
bits = 3
step = 256 // (2 ** bits)
quant = (img // step) * step
2

Bagian 2 · 4 menit

Representasi

Histogram intensitas: sumbu x = nilai 0–255, sumbu y = jumlah piksel.

Bentuk yang sama bisa dilihat dari beberapa sudut. Bagi program, gambar RGB adalah tensor 3 dimensi: tinggi × lebar × channel. Grayscale memadatkannya menjadi matriks 2D. Ruang warna HSV memisahkan warna (hue) dari kecerahan, sehingga lebih tahan terhadap perubahan pencahayaan.

Isi matriks di titik terpilih

Klik gambar untuk memindahkan titik. Potongan 6 × 6 piksel.

Rumus grayscale (luminansi ITU-R BT.601): Y = 0.299R + 0.587G + 0.114B. Hijau mendapat bobot terbesar karena mata manusia paling peka terhadapnya.

Kode Python: ruang warna dan histogram
import cv2, numpy as np
import matplotlib.pyplot as plt

R, G, B = img[..., 0], img[..., 1], img[..., 2]
gray = cv2.cvtColor(img, cv2.COLOR_RGB2GRAY)   # (240, 320)
hsv  = cv2.cvtColor(img, cv2.COLOR_RGB2HSV)    # H: 0–179 di OpenCV

print(gray[100:106, 150:156])                # potongan matriks 6x6

for i, c in enumerate("rgb"):
    plt.plot(cv2.calcHist([img], [i], None, [256], [0, 256]), color=c)
plt.show()
3

Bagian 3 · 6 menit

Preprocessing

Sebelum
Sesudah
Histogram sebelum
Histogram sesudah

Data mentah jarang langsung siap dipakai. Preprocessing menyeragamkan ukuran, membersihkan noise, dan memperjelas pola. Urutan langkah di bawah mengikuti urutan pipeline yang umum.

0%
128
0

Coba skenario ini: naikkan noise ke 8%, lalu bandingkan filter Gaussian dengan Median. Median jauh lebih efektif untuk noise salt & pepper karena nilai ekstrem tidak ikut dirata-ratakan.

Normalisasi

Model belajar lebih stabil jika nilai berada di skala kecil. Statistik dari gambar hasil di sebelah kiri:

Kode Python: pipeline preprocessing
import cv2, numpy as np

small = cv2.resize(img, (160, 120), interpolation=cv2.INTER_AREA)
gray  = cv2.cvtColor(small, cv2.COLOR_RGB2GRAY)

blur  = cv2.GaussianBlur(gray, (5, 5), 0)
med   = cv2.medianBlur(gray, 5)                 # ampuh untuk salt & pepper
eq    = cv2.equalizeHist(med)

t, biner = cv2.threshold(eq, 0, 255, cv2.THRESH_BINARY + cv2.THRESH_OTSU)
print("ambang Otsu:", t)

flip  = cv2.flip(small, 1)                      # augmentasi
x01   = small.astype(np.float32) / 255.0        # min-max ke [0,1]
z     = (small - small.mean()) / small.std()    # standardisasi
4

Bagian 4 · 5 menit

Feature extraction

Gradien Gx (perubahan horizontal)
Gradien Gy (perubahan vertikal)
Magnitudo √(Gx² + Gy²)
Peta tepi biner

Panjang vektor fitur

0

Kode Python: ekstraksi fitur
import cv2, numpy as np
from skimage.feature import hog, local_binary_pattern

# 1. Tepi
gx  = cv2.Sobel(gray, cv2.CV_64F, 1, 0, ksize=3)
gy  = cv2.Sobel(gray, cv2.CV_64F, 0, 1, ksize=3)
mag = np.hypot(gx, gy)
canny = cv2.Canny(gray, 100, 200)

# 2. Histogram warna (8 bin per channel)
hist = np.concatenate([np.histogram(img[..., c], 8, (0, 256))[0] for c in range(3)])
hist = hist / hist.reshape(3, 8).sum(1).repeat(8)

# 3. HOG
fitur_hog, vis = hog(gray, orientations=9, pixels_per_cell=(16, 16),
                     cells_per_block=(2, 2), visualize=True)

# 4. Tekstur LBP
lbp = local_binary_pattern(gray, P=8, R=1, method="default")
fitur_lbp, _ = np.histogram(lbp, bins=256, range=(0, 256), density=True)

X = np.concatenate([hist, fitur_hog, fitur_lbp])   # siap untuk model
✓

Penutup · 1 menit

Ringkasan pipeline

Data gambargrid piksel, 8 bit/channel
→
Representasitensor H×W×C, RGB/Gray/HSV
→
Preprocessingresize, denoise, kontras, normalisasi
→
Fiturtepi, warna, HOG, LBP
→
ModelSVM, Random Forest, k-NN