Files
MelvynFaith 003b2c544c Jawaban UTS Pengolahan Citra Digital Kelompok I
Soal 1: selisih Laplacian of Gaussian (sigma 0,1 dan 0,2).
Soal 2: memecah teks menjadi karakter individual dengan regionprops.
Soal 3: menghitung jumlah koin per ukuran dengan regionprops.
2026-10-22 23:43:56 +07:00

12 KiB
Raw Permalink Blame History

Soal 3 — Menghitung Jumlah Koin untuk Setiap Ukuran dengan regionprops

Program: pengolahan_citra.py · Input: koin_100.png (dibuat oleh buat_gambar_koin.py dari koin.png) · Output: folder output/

Cara menjalankan:

pip install -r requirements.txt
python buat_gambar_koin.py        # membuat koin_100.png
python pengolahan_citra.py        # atau: python pengolahan_citra.py <gambar_koin>

Referensi teori: Gonzalez & Woods, Digital Image Processing, edisi ke-4 (Pearson, 2018).

1. Tujuan dan Asumsi

Sebuah gambar berisi 100 koin dengan berbagai ukuran di atas latar belakang seragam, dan koin-koin tidak saling bersentuhan. Program harus menentukan jumlah koin untuk setiap ukuran.

Asumsi yang dipakai:

  • Koin tidak bersentuhan, sesuai soal. Akibatnya satu komponen terhubung = satu koin.
  • Latar belakang seragam dan kontras terhadap koin.
  • Jumlah dan nilai ukuran koin tidak diketahui sebelumnya. Program mengelompokkan ukuran secara otomatis dari data diameter.

2. Gambar Uji

Soal tidak menyertakan gambar. koin.png hanya berisi satu koin, jadi buat_gambar_koin.py menyusun gambar uji koin_100.png (3000 × 3000 piksel):

  • Koin diperkecil ke 4 ukuran dan ditempel 100 kali di posisi acak.
  • Jarak antar-tepi koin minimal 10 piksel, jadi tidak ada yang bersentuhan.
  • Latar abu-abu gelap seragam (nilai 40).
  • Setiap koin diputar acak dan seluruh gambar diberi noise Gaussian (σ = 3), supaya koin sejenis tidak identik piksel per piksel, seperti pada foto asli.
  • Seed acak tetap, jadi gambar yang sama bisa dibuat ulang.
Diameter tempel Jumlah koin
140 piksel 30
170 piksel 27
205 piksel 25
245 piksel 18
Total 100

Karena jumlah per ukuran diketahui, hasil program dapat diperiksa.

Gambar uji koin_100.png

3. Kode Semu

INPUT : citra RGB berisi koin
OUTPUT: daftar (ukuran, jumlah koin, diameter rata-rata)

1.  gray  ← konversi citra ke grayscale
2.  gray  ← Gaussian blur 5×5 (gray)
3.  T     ← threshold Otsu dari histogram gray
4.  mask  ← (gray > T)
5.  JIKA mayoritas piksel tepi gambar bernilai 1 MAKA mask ← NOT mask
        (agar koin = 1 dan latar = 0)
6.  mask  ← isi lubang (mask)
7.  label ← labeling komponen terhubung 8-ketetanggaan (mask)
8.  label ← buang komponen yang menyentuh tepi gambar (label)
9.  daftar_koin ← kosong
10. UNTUK SETIAP region DALAM regionprops(label):
        JIKA region.area < MIN_AREA: lanjutkan          (noise)
        d ← √(4 · region.area_convex / π)              (diameter koin)
        tambahkan (region.label, d, region.centroid) ke daftar_koin
11. kelompok ← kosong
12. UNTUK SETIAP koin DALAM daftar_koin, terurut dari diameter terkecil:
        cari kelompok k dengan |d − rata2(k)| / rata2(k) ≤ TOLERANSI
        JIKA ada: masukkan koin ke kelompok yang paling dekat
        JIKA tidak: buat kelompok baru berisi koin tersebut
13. urutkan kelompok berdasarkan diameter rata-rata
14. UNTUK SETIAP kelompok: tampilkan (nomor ukuran, jumlah anggota, diameter rata-rata)
15. simpan tabel CSV, mask, dan gambar anotasi

4. Penjelasan Setiap Langkah

4.1 Grayscale dan penghalusan (Bab 2, Bab 3, Bab 7)

Citra warna BGR diubah ke satu kanal intensitas (cv2.cvtColor) dengan kombinasi linear:

Y = 0,299 R + 0,587 G + 0,114 B

Lalu citra dihaluskan dengan kernel Gaussian 5 × 5 (cv2.GaussianBlur). Ini filter penghalus spasial linear dari Bab 3:

G(s, t) = K · e^(−(s² + t²) / 2σ²)

Dengan argumen σ = 0, OpenCV menghitung σ dari ukuran kernel, yaitu σ = 0,3·((5 − 1)·0,5 − 1) + 0,8 = 1,1. Penghalusan meredam noise sehingga threshold tidak menghasilkan bintik-bintik di latar.

4.2 Threshold Otsu

Citra biner diperoleh dengan:

mask(x, y) = 1  jika f(x, y) > T
mask(x, y) = 0  jika f(x, y) ≤ T

Nilai T dipilih otomatis dengan metode Otsu, yaitu nilai k yang memaksimalkan varians antar-kelas:

σ²_B(k) = [m_G · P₁(k) − m(k)]² / [P₁(k) · (1 − P₁(k))]

dengan P₁(k) = proporsi piksel ≤ k, m(k) = rata-rata kumulatif sampai k, dan m_G = rata-rata global. Latar yang seragam membuat histogram bimodal (latar dan koin), sehingga Otsu cocok. Pada koin_100.png, T = 126.

Catatan: metode Otsu dibahas di Bab 10 (Segmentasi), setelah materi UTS. Konsep fungsi thresholding sudah dibahas di Bab 3.

4.3 Polaritas

Koin bisa lebih terang atau lebih gelap dari latar. Program memeriksa piksel di keempat tepi gambar: jika lebih dari separuhnya bernilai 1, berarti latar ikut terdeteksi sebagai objek, dan mask dibalik. Pada koin_100.png, 0% piksel tepi bernilai 1, jadi mask tidak dibalik.

4.4 Pengisian lubang (Bab 9)

Relief koin (bintang, simbol $) dan pantulan cahaya bisa membuat sebagian piksel di dalam koin berada di bawah T. Akibatnya koin berlubang, atau bahkan terpecah menjadi beberapa komponen. Lubang adalah daerah latar yang dikelilingi objek. Lubang diisi dengan algoritma morfologi:

X_k = (X_{k−1} ⊕ B) ∩ Iᶜ,   k = 1, 2, 3, ...

dengan I = mask, Iᶜ = komplemennya, dan B = elemen penstruktur. Iterasi berhenti saat X_k = X_{k−1}, lalu hasilnya X_k ∪ I. binary_fill_holes menjalankan versi otomatisnya: setiap daerah latar yang tidak terhubung ke tepi gambar dianggap lubang dan diisi. Pada koin_100.png, 31.941 piksel lubang terisi.

4.5 Labeling komponen terhubung (Bab 2 dan Bab 9)

label(mask, connectivity=2) memberi nomor unik pada setiap komponen terhubung dengan 8-ketetanggaan: piksel p terhubung dengan 8 tetangganya, yaitu 4 horizontal/vertikal dan 4 diagonal. Secara morfologi, satu komponen yang memuat titik awal X₀ diekstraksi dengan:

X_k = (X_{k−1} ⊕ B) ∩ I

Karena koin tidak bersentuhan, setiap koin menjadi tepat satu komponen. Pada koin_100.png terbentuk 450 komponen: 100 koin dan 350 fragmen kecil, yaitu potongan tepi koin yang terpisah oleh bagian bayangan.

4.6 Membuang koin di tepi gambar (Bab 9)

Koin yang terpotong tepi gambar luasnya tidak utuh, sehingga diameternya terukur lebih kecil dan bisa masuk ke kelompok ukuran yang salah. clear_border membuang setiap komponen yang menyentuh tepi gambar. Di buku, operasi ini disebut border clearing dan dilakukan dengan rekonstruksi morfologi. Pada koin_100.png tidak ada koin di tepi. Pada uji D (bagian 6), langkah ini membuang satu koin yang terpotong.

4.7 Cara regionprops digunakan

regionprops(label) menghasilkan satu objek pengukuran per komponen. Properti yang dipakai:

Properti Arti Kegunaan di program
area Jumlah piksel region Membuang noise: region dengan area < 100 piksel diabaikan
area_convex Jumlah piksel convex hull region Menghitung diameter koin
centroid Titik pusat region (rata-rata koordinat piksel) Posisi lingkaran dan nomor ukuran pada gambar anotasi
label Nomor region Identitas koin

Filter area. Pada koin_100.png, fragmen terbesar berukuran 37 piksel dan koin terkecil 13.484 piksel. Batas 100 piksel memisahkan keduanya dengan aman, jadi 350 fragmen terbuang dan tepat 100 koin tersisa.

Diameter dari convex hull. Bayangan di tepi koin cukup gelap sehingga berada di bawah T. Mask koin menjadi lingkaran yang terpotong berbentuk sabit di satu sisi. Potongan ini terbuka ke latar, jadi tidak terisi oleh pengisian lubang. Convex hull H dari region adalah himpunan konveks terkecil yang memuat region tersebut (algoritma morfologi di Bab 9). Convex hull menutup potongan sabit, sehingga luasnya mendekati luas lingkaran utuh. Diameter dihitung sebagai diameter lingkaran yang luasnya sama dengan luas convex hull:

A_H = π (d/2)²   →   d = √(4 · A_H / π)

Perbandingan pada koin_100.png:

Diameter tempel d dari area d dari area_convex
140 131,1 (93,6%) 137,2 (98,0%)
170 159,4 (93,7%) 167,3 (98,4%)
205 192,4 (93,8%) 202,3 (98,7%)
245 230,2 (93,9%) 242,2 (98,9%)

Catatan: deskriptor region seperti area dan centroid dibahas lebih lanjut di Bab 11. Program memakainya lewat regionprops, sesuai petunjuk soal.

4.8 Pengelompokan ukuran

Diameter diurutkan dari terkecil. Setiap koin dibandingkan dengan diameter rata-rata setiap kelompok yang sudah ada. Koin masuk ke kelompok terdekat jika selisih relatifnya ≤ toleransi:

|d − d̄_k| / d̄_k × 100% ≤ 3%

Jika tidak ada kelompok yang memenuhi, koin membentuk kelompok baru. Jumlah kelompok tidak ditentukan di awal, tetapi muncul dari data.

Pemilihan toleransi. Toleransi harus lebih besar dari variasi diameter koin sejenis, tetapi lebih kecil dari selisih antar-ukuran:

  • Variasi diameter koin sejenis pada koin_100.png paling besar 0,21% dari rata-rata kelompoknya.
  • Selisih antar-ukuran yang berdekatan 19,7–22,0%.
  • Pada uji C (bagian 6), ukuran berbeda sekitar 7%. Toleransi 8% menggabungkan ukuran-ukuran itu, sedangkan 3% memisahkannya dengan benar.

5. Hasil

Output program pada koin_100.png:

Jumlah koin terdeteksi: 100

Hasil pengelompokan ukuran:
Ukuran | Jumlah koin | Diameter rata-rata (piksel)
     1 |          30 |                       137.17
     2 |          27 |                       167.29
     3 |          25 |                       202.27
     4 |          18 |                       242.21
Ukuran Diameter tempel Jumlah sebenarnya Jumlah dari program
1 140 30 30
2 170 27 27
3 205 25 25
4 245 18 18

Semua jumlah tepat. File output di folder output/:

  • jumlah_koin_per_ukuran.csv: tabel hasil.
  • mask_koin.png: hasil segmentasi setelah pengisian lubang.
  • anotasi_koin.jpg: setiap koin dilingkari dan diberi nomor ukuran, dengan warna berbeda per ukuran.
Mask segmentasi Anotasi
mask anotasi

6. Pengujian Tambahan

Untuk menguji ketahanan program, dibuat 4 gambar sintetis tambahan, masing-masing berisi koin berbentuk lingkaran yang tidak bersentuhan dengan noise Gaussian. Setiap gambar diuji dengan versi awal program (tanpa pengisian lubang, tanpa clear_border, toleransi 8%) dan versi akhir.

Uji Kondisi Jumlah sebenarnya Versi awal Versi akhir
A Koin polos, 3 ukuran 40 / 35 / 25 40 / 35 / 25 40 / 35 / 25
B Koin dengan relief gelap di dalam 40 / 35 / 25 200 koin, 6 ukuran 40 / 35 / 25
C 4 ukuran, selisih sekitar 7% 30 / 25 / 25 / 20 55 / 45 30 / 25 / 25 / 20
D 3 ukuran, ditambah 1 koin terpotong tepi 40 / 35 / 24 + 1 terpotong 40 / 36 / 24 40 / 35 / 24
  • Uji B menunjukkan pentingnya pengisian lubang. Relief membelah setiap koin menjadi cincin luar dan bagian dalam, sehingga satu koin terhitung dua.
  • Uji C menunjukkan pentingnya toleransi yang tepat.
  • Uji D menunjukkan pentingnya clear_border. Pada versi akhir, program juga mencetak peringatan karena jumlah koin utuh (99) berbeda dari 100.

7. Batasan

  • Koin bersentuhan. Koin yang bersentuhan menjadi satu komponen dan terhitung satu koin besar. Ini sesuai asumsi soal. Untuk kasus bersentuhan diperlukan teknik pemisahan seperti watershed.
  • Parameter bergantung pada gambar. MIN_COIN_AREA (100 piksel) bergantung pada resolusi. Toleransi 3% bergantung pada seberapa mirip ukuran-ukuran koin dan seberapa besar variasi pengukuran. Pada foto asli, kedua nilai ini perlu dicek ulang.
  • Ukuran dalam piksel. Diameter dinyatakan dalam piksel. Untuk ukuran dalam milimeter diperlukan benda acuan berukuran diketahui di dalam gambar.
  • Perspektif. Jika foto diambil miring, koin tampak elips dan koin yang lebih jauh tampak lebih kecil. Foto sebaiknya diambil tegak lurus dari atas.