Segmentasi Citra: Deteksi Tepi Menggunakan Operator Canny
Table of Contents
Operator Canny, yang dikemukakan oleh John Canny pada tahun 1986, terkenal sebagai operator deteksi tepi yang optimal. Algoritma ini memberikan tingkat kesalahan yang rendah, melokalisasi titik-titik tepi (jarak piksel-piksel tepi yang ditemukan deteksi dan tepi yang sesungguhnya sangat pendek), dan hanya memberikan satu tanggapan untuk satu tepi. Menurut Green (2012), terdapat enam langkah yang dilakukan untuk mengimplementasikan deteksi tepi Canny. Keenam langkah tersebut dijabarkan berikut ini :
Langkah 1
Pertama, dilakukan penipisan terhadap citra dengan tujuan untuk menghilangkan derau. Hal ini dapat dilakukan dengan menggunakan filter Gaussian dengan cadar sederhana. Cadar yang digunakan berukuran jauh lebih kecil daripada ukuran citra. Contoh ditunjukkan pada Gambar 1 :
Gambar 1 : Contoh cadar Gaussian dengan theta = 1,4 |
Setelah penghalusan gambar terhadap derau dilakukan, dilakukan proses untuk mendapatkan kekuatan tepi (edge strength). Hal ini dilakukan dengan menggunakan operator Gaussian. Selanjutnya, gradien citra dapat dihitung melalui rumus :
Langkah 3
Langkah ketiga berupa penghitungan arah tepi. Rumus yang digunakan untuk keperluan ini :
Langkah 4
Setelah arah tepi diperoleh, perlu menghubungkan antara arah tepi dengan sebuah arah yang dapat dilacak dari citra. Sebagai contoh, terdapat susunan piksel berukuran 5 x 5 seperti terlihat pada Gambar 2. Dengan melihat piksel “a” tampak bahwa a hanya memiliki 4 arah berupa 0 derajat, 45 derajat, 90 derajat, dan 135 derajat.
Gambar 2 : Matrik piksel berukuran 5x5 |
Selanjutnya, arah tepi yang diperoleh akan dimasukkan ke dalam salah satu kategori dari keempat arah tadi berdasarkan area yang tertera pada Gambar 3. Berikut adalah aturan konversi yang berlaku :
Gambar 3 : Area mengkonversi arah tepi ke dalam kategori salah satu arah dari 00,45,90,135 derajat |
- Semua arah tepi yang berkisar antara 0 dan 22,5 serta 157,5 dan 180 derajat (warna biru) diubah menjadi 0 derajat.
- Semua arah tepi yang berkisar antara 22,5 dan 67,5 derajat (warna kuning) diubah menjadi 45 derajat.
- Semua arah tepi yang berkisar antara 67,5 dan 112,5 derajat (warna merah) diubah menjadi 90 derajat.
- Semua arah tepi yang berkisar antara 112,5 dan 157,5 derajat (warna hijau) diubah menjadi 135 derajat.
Setelah arah tepi diperoleh, penghilangan non-maksimum dilaksanakan. Penghilangan non-maksimum dilakukan di sepanjang tepi pada arah tepi dan menghilangkan piksel-piksel (piksel diatur menjadi 0) yang tidak dianggap sebagai tepi. Dengan cara seperti itu, diperoleh tepi yang tipis.
Langkah 6
Langkah keenam berupa proses yang disebut hysteresis. Proses ini menghilangkan garis-garis yang seperti terputus-putus pada tepi objek. Caranya adalah dengan menggunakan dua ambang T1 dan T2. Lalu, semua piksel citra yang bernilai lebih besar daripada T1 dianggap sebagai piksel tepi. Selanjutnya, semua piksel yang terhubung dengan piksel tersebut dan memiliki nilai lebih besar dari T2 juga dianggap sebagai piksel tepi.
Bagian penting yang perlu dijelaskan adalah penghilangan non-maksimum dan peng-ambangan histeresis. Penghilangan non-maksimum dilakukan dengan mula-mula menyalin isi larik Grad (yang berisi besaran gradien) ke Non_max. Selanjutnya, penghilangan non-maksimum dilaksanakan dengan memperhatikan dua titik tetangga yang terletak pada arah tepi (yang tersimpan dalam Theta). Misalnya, arah tepi adalah 0. Apabila titik yang menjadi perhatian mempunyai koordinat (r, c), dua titik tetangga berupa (r, c-1) dan (r, c+1). Apabila gradien titik perhatian lebih besar daripada gradien kedua tetangga, nilainya akan dipertahankan. Sebaliknya, jika nilai titik perhatian lebih kecil daripada nilai salah satu atau kedua gradien tetangga, nilainya akan diabaikan (diubah menjadi nol). Seluruh kemungkinan proses seperti itu dijabarkan dalam Gambar 4 :
Gambar 4 : Penghilangan Non-Maksimum |
Peng-ambangan histeresis dilakukan dengan melibatkan dua ambang T1 (ambang bawah) dan ambang T2 (ambang atas). Nilai yang kurang dari T1 akan diubah menjadi hitam (nilai 0) dan nilai yang lebih dari T2 diubah menjadi putih (nilai 255). Lalu, bagaimana nilai yang lebih dari atau sama dengan T1 tetapi kurang dari T2? Oleh karena itu, untuk sementara nilai pada posisi seperti itu diberi nilai 128, yang menyatakan nilai abu-abu atau belum jelas, akan dijadikan 0 atau 255.
Selanjutnya, dilakukan pengujian untuk mendapatkan kondisi seperti tercantum pada Gambar 5. Apabila kondisi seperti itu terpenuhi, angka 128 diubah menjadi 255. Proses pengujian seperti itu dilakukan sampai tidak ada lagi perubahan dari nilai 128 menjadi 255. Tahap selanjutnya, semua piksel yang bernilai 128 yang tersisa diubah menjadi nol.
Gambar 5 : Pengujian untuk mengubah nilai 128 menjadi 255 |
function [K] = canny(F, ambang_bawah, ambang_atas) % Pemerolehan tepi objek pada citra F % melalui operator Canny % Argumen: % ambang_bawah = batas bawah untuk ambang histeresis % Nilai bawaan 011 % ambang_atas = batas atas untuk ambang histeresis % Nilai bawaan 0,3 % Hasil: citra G % Menentukan nilai ambang bawaan if nargin < 2 ambang_bawah = 0.1; end if nargin < 2 ambang_atas = 0.3; end % Kernel Gaussians HG = [ 2 4 5 4 2 4 9 12 9 12 5 12 15 12 5 4 9 12 9 12 2 4 5 4 2 ] / 115.0; [hHG, wHG] = size(HG); h2 = floor(hHG / 2); w2 = floor(wHG / 2); % Kenakan operasi Gaussian G = double(deteksi(F, HG, true)); % Pastikan hasilnya berada antara 0 sampai dengan 255 [m, n] = size(G); for i = 1 : m for j = 1 : n G(i, j) = round(G(i, j)); if G(i, j) > 255 G(i, j) = 255; else if G(i, j) < 0 G(i, j) = 0; end end end end % Kenakan perhitungan gradien dan arah tepi Theta = zeros(m, n); Grad = zeros(m, n); for i = 1 : m-1 for j = 1 : n-1 gx = (G(i,j+1)-G(i,j) + ... G(i+1,j+1)-G(i+1,j)) / 2; gy = (G(i,j)-G(i+1,j) + ... G(i,j+1)-G(i+1,j+1)) / 2; Grad(i, j) = sqrt(gx.^2 + gy.^2); Theta(i,j) = atan2(gy, gx); end end % Konversi arah tepi menjadi 0, 45, 90, atau 135 derajat [r c] = size (Theta); if Theta < 0 Theta = Theta + pi; % Jangkauan menjadi 0 s/d pi end for i = 1 : r for j = 1 : c if (Theta(i,j) < pi/8 || Theta(i,j) >= 7/8*pi) Theta(i,j) = 0; elseif (Theta(i,j)>=pi/8 && Theta(i,j) < 3*pi/8 ) Theta(i,j) = 45; elseif (Theta(i,j) >=3*pi/8 && Theta(i,j) < 5*pi/8 ) Theta(i,j) = 90; else Theta(i,j) = 135; end end end % penghilangan non-maksimum Non_max = Grad; for i = 1+h2 : r-h2 for j = 1+w2 : c-h2 if Theta(i,j) == 0 if (Grad(i,j) <= Grad(i,j+1)) || ... (Grad(i,j)<= Grad(i,j-1)) Non_max(i,j) = 0; end elseif Theta(i,j) == 45 if (Grad(i,j) <= Grad(i-1,j+1)) || ... (Grad(i,j) <= Grad(i+1,j-1)) Non_max(i,j) = 0; end elseif Theta(i,j) == 90 if (Grad(i,j) <= Grad(i+1,j) ) || ... (Grad(i,j) <= Grad(i-1,j)) Non_max(i,j) = 0; end else if (Grad(i,j) <= Grad(i+1,j+1)) || ... (Grad(i,j) <= Grad(i-1,j-1)) Non_max(i,j) = 0; end end end end % Pengambangan histeresis ambang_bawah = ambang_bawah * max(max(Non_max)); ambang_atas = ambang_atas * max(max(Non_max)); Histeresis = Non_max; % ----- Penentuan awal untuk memberikan nilai % ----- 0, 128, dan 255 for i = 1+h2 : r-h2 for j = 1+w2 : c-w2 if (Histeresis(i,j) >= ambang_atas) Histeresis(i,j) = 255; end if (Histeresis(i,j) < ambang_atas) && ... (Histeresis(i,j) >= ambang_bawah) Histeresis(i,j)= 128; end if (Histeresis(i,j) < ambang_bawah) Histeresis(i,j) = 0; end end end % ----- Penggantian angka 128 menjadi 255 % ----- Berakhir kalau tidak ada lagi yang berubah ulang = true; while ulang ulang = false; for i = 1+h2 : r-h2 for j = 1+w2 : c-w2 if (Histeresis(i,j) == 128) if (Histeresis(i-1, j-1) == 255) && ... (Histeresis(i-1, j) == 255) && ... (Histeresis(i, j+1) == 255) && ... (Histeresis(i, j-1) == 255) && ... (Histeresis(i, j+1) == 255) && ... (Histeresis(i+1, j-1) == 255) && ... (Histeresis(i+1, j) == 255) && ... (Histeresis(i+1, j+1) == 255) Histeresis(i,j) = 255; ulang = true; end end end end end % ----- Penggantian angka 128 menjadi 0 % ----- untuk yang tersisa for i = 1+h2 : r-h2 for j = 1+w2 : c-w2 if (Histeresis(i,j) == 128) Histeresis(i,j) = 0; end end end % Buang tepi for i = 1+h2 : r-h2 for j = 1+w2 : c-w2 K(i-1,j-1) = Histeresis(i,j); end end
Simpan program diatas dengan nama canny.m, dan jangan lupa untuk menuliskan program berikut simpan dengan nama deteksi.m, jadi kita memiliki dua file yang saling berhubungan.
function[G] = deteksi(F,H,potong,pembulatan) %deteksi melalukan operasi korelasi kernel H dengan citra F %H harus mempunyai tinggi dan lebar ganjil %Argumen potong bersifat opsional. Apabila bernilai true bagian citra yang %tidak diproses akan dipotong, bawaan = false %Argumen pembulatan bersifat opsional. Apabila bernilai true, pembulatan %dengan uint8 tidak dilakukan, Bawaan = false %Hasil = citra G if nargin < 3 potong = false ; end if nargin < 4 pembulatan = true ; end [tinggi_f,lebar_f]=size(F); [tinggi_h,lebar_h]=size(H); if rem(lebar_h,2)==0 || rem(tinggi_h,2)==0 disp('Lebar dan tinggi H harus ganjil'); return ; end m2=floor(tinggi_h/2); n2=floor(lebar_h/2); %menentukan ukuran hasil beserta penentu ofset koordinat if potong==true sisi_m2=m2; sisi_n2=n2; G = zeros(tinggi_f-2*m2,lebar_f-2*n2); else sisi_m2=0; sisi_n2=0; G = zeros(size(F)); end F2=double(F); for y=m2+1 : tinggi_f-m2 for x=n2+1 : lebar_f-n2 % pelaksanaan korelasi F(baris,kolom) jum=0 ; for p =-m2 : m2 for q=-n2 : n2 jum=jum+H(p+m2+1,q+n2+1)*... F2(y+p,x+q); end end G(y-sisi_m2,x-sisi_n2)=jum; end end if pembulatan == true G=uint8(G); end
kemudian kita terapkan program canny.m pada sebuah citra. Citra yang saya gunakan adalah citra kucing berskala keabuan (grayscale) berikut :
Program kita jalankan menggunakan matlab :
Gambar 6 : Gambar kucing |
implementasi canny diatas menggunakan peng-ambangan berupa 0.05 untuk batas bawah dan 0.15 untuk batas atas. Hasilnya seperti gambar 7 :
Gambar 7 : Hasil operator Canny |
Semoga penjelasan tersebut bermanfaat bagi teman-teman....
Salam