Pertemuan 13

Pertemuan 13

Praktikum Pengolahan Citra Digital: Analisis & Klasifikasi Objek

Instruksi Mahasiswa: Bacalah narasi analisis pada setiap blok kode di bawah ini. Sebelum menjalankan/melengkapi kode program, salin pertanyaan analisis yang ada dalam komentar dan tuliskan jawabannya pada Laporan Praktikum Anda!
image_processing_pipeline.py (Python / OpenCV) Tugas Reflektif & Analisis Kode

Library yang Dibutuhkan

Sebelum menjalankan skrip di atas, pastikan modul/library OpenCV dan Scikit-Image sudah terinstall:

Bash
pip install opencv-python numpy matplotlib scikit-image

Penjelasan Kode Menurut Abstraksi:

  1. Low-Level Processing (Input: Gambar -> Output: Gambar)

    • cv2.GaussianBlur: Mengeliminasi derau (noise) frekuensi tinggi.

    • cv2.equalizeHist: Meratakan distribusi tingkat keabuan untuk mempertajam kontras.

  2. Mid-Level Processing (Input: Gambar -> Output: Fitur/Atribut)

    • cv2.threshold & cv2.findContours: Memisahkan objek dari background dan melacak batas area (segmentasi).

    • cv2.contourArea, cv2.arcLength, graycoprops: Ekstraksi fitur geometri (luas, keliling, circularity) dan tekstur (GLCM Contrast & Homogeneity).

  3. High-Level Processing (Input: Fitur -> Output: Keputusan/Pengenalan)

    • Logika kondisional (if circularity > 0.8) memberikan interpretasi semantis untuk mengenali objek sebagai Persegi atau Lingkaran.

import cv2
import numpy as np
import matplotlib.pyplot as plt
from skimage.feature import graycomatrix, graycoprops

# ==============================================================================
# 0. PREPARATION: Synthetic Image Generation & Noise Ingestion
# ==============================================================================

# [ANALISIS DATA 1]: Pembuatan Matriks Citra Sintetik
# PERTANYAAN 1.1: Mengapa nilai piksel awal diisi dengan angka 30 dan tipe data uint8? 
# PERTANYAAN 1.2: Apa yang terjadi jika matriks citra diisi dengan tipe int32 atau float64?
img_size = (300, 300)
image = np.zeros(img_size, dtype=np.uint8) + 30

# Deklarasi Objek Geometry
cv2.rectangle(image, (40, 40), (140, 140), 200, -1)   # Objek A: Persegi
cv2.circle(image, (220, 200), 45, 180, -1)           # Objek B: Lingkaran

# [EVALUASI SIMULASI]: Pengaruh Gaussian Noise
# TUGAS: Jika nilai deviasi standar noise (sekarang 15) dinaikkan menjadi 50, 
# analisis dampaknya terhadap keberhasilan deteksi bentuk pada tahap segmentasi!
np.random.seed(42)
noise = np.random.normal(0, 15, img_size).astype(np.int16)
noisy_image = np.clip(image.astype(np.int16) + noise, 0, 255).astype(np.uint8)


# ==============================================================================
# 1. LOW-LEVEL PROCESSING: Enhancements & Noise Mitigation
# ==============================================================================

# [ANALISIS ALGORITMA 1]: Reduksi Noise
# PERTANYAAN: Mengapa kita menggunakan Gaussian Filter kernel (5,5) dan bukan Median Filter? 
# Tuliskan perbedaan mendasar dampak kedua filter ini terhadap tepi (edge) objek!
filtered_image = cv2.GaussianBlur(noisy_image, (5, 5), 0)

# [ANALISIS ALGORITMA 2]: Histogram Equalization
# JELASKAN: Apa fungsi equalization di sini terhadap distribusi tingkat keabuan (grayscale), 
# dan mengapa langkah ini mempermudah proses Otsu Thresholding selanjutnya?
equalized_image = cv2.equalizeHist(filtered_image)


# ==============================================================================
# 2. MID-LEVEL PROCESSING: Binarization & Contour Detection
# ==============================================================================

# [EKSPERIMEN LOGIKA]: Otsu Automatic Thresholding
# TUGAS: Catat nilai threshold otomatis yang dihasilkan oleh algoritma Otsu ini! 
# Mengapa thresholding manual sering gagal jika diterapkan pada citra bernoise?
_, binary_thresh = cv2.threshold(equalized_image, 0, 255, cv2.THRESH_BINARY + cv2.THRESH_OTSU)

# Extraction Boundary Kontur
contours, _ = cv2.findContours(binary_thresh, cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_SIMPLE)


# ==============================================================================
# 3. HIGH-LEVEL PROCESSING: Feature Extraction & Classification
# ==============================================================================

output_image = cv2.cvtColor(equalized_image, cv2.COLOR_GRAY2BGR)
print("=== HASIL EKSTRAKSI FITUR & KLASIFIKASI OBJEK ===")

for i, cnt in enumerate(contours):
    area = cv2.contourArea(cnt)
    perimeter = cv2.arcLength(cnt, True)
    
    # Filter noise kontur palsu
    if area < 500 or perimeter == 0:
        continue
    
    # [MATEMATIKA FITUR]: Metric Circularity (Form Factor)
    # PERTANYAAN MATEMATIS: Secara teori, berapa nilai circularity ideal untuk lingkaran sempurna? 
    # Mengapa nilainya bisa berada di bawah angka 1.0 pada citra digital ini?
    circularity = (4 * np.pi * area) / (perimeter ** 2)
    
    # [EKSTRAKSI FITUR TEKSTUR]: GLCM Matrix
    # JELASKAN: Apa arti dari nilai 'contrast' dan 'homogeneity' yang dihasilkan dari GLCM?
    x, y, w, h = cv2.boundingRect(cnt)
    roi = equalized_image[y:y+h, x:x+w]
    
    glcm = graycomatrix(roi, distances=[1], angles=[0], levels=256, symmetric=True, normed=True)
    contrast = graycoprops(glcm, 'contrast')[0, 0]
    homogeneity = graycoprops(glcm, 'homogeneity')[0, 0]
    
    # [LOGIKA KEPUTUSAN]: Rule-Based Classification
    # PERTANYAAN: Mengapa angka boundary threshold circularity diset pada 0.8? 
    # Apa akibatnya jika threshold ini diturunkan menjadi 0.5?
    if circularity > 0.8:
        label = "Lingkaran"
        color = (0, 255, 0)  # BGR: Hijau
    else:
        label = "Persegi"
        color = (255, 0, 0)  # BGR: Biru
        
    # Menghitung Momen Citra untuk Titik Tengah Label
    M = cv2.moments(cnt)
    cx = int(M["m10"] / M["m00"])
    cy = int(M["m01"] / M["m00"])
    
    cv2.drawContours(output_image, [cnt], -1, color, 2)
    cv2.putText(output_image, label, (cx - 35, cy), cv2.FONT_HERSHEY_SIMPLEX, 0.6, color, 2)
    
    # Output Konsol Praktikum
    print(f"\n[Objek #{i+1}: {label}]")
    print(f"  - Luas (Area)         : {area} px")
    print(f"  - Keliling            : {perimeter:.2f} px")
    print(f"  - Kebulatan           : {circularity:.4f}")
    print(f"  - Tekstur Contrast    : {contrast:.4f}")
    print(f"  - Tekstur Homogeneity : {homogeneity:.4f}")


# ==============================================================================
# 4. VISUALISASI PROSES (Pipelining)
# ==============================================================================

# TODO (TUGAS MAHASISWA): 
# Buatlah plot subplot 2x3 menggunakan Matplotlib untuk menampilkan ke-5 tahapan citra 
# di atas beserta subplot ke-6 yang menampilkan histogram dari equalized_image!
# Tuliskan kode lengkap plot Anda di bawah ini:

# [LENGKAPKAN KODE PLOT MATPLOTLIB DI SINI]