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
Langkah 2 
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.
Langkah 5
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
berikut ini adalah implementasi operator Canny pada pemrograman matlab. 
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 :
Gambar 6 : Gambar kucing
Program kita jalankan menggunakan matlab : 





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 
Dinukil dari buku Teori dan Aplikasi Pengolahan Citra karya Abdul Kadir dan Adhi Susanto

1 comment

Terima kasih telah mampir di blog kami. Jika ingin menghubungi penulis, silakan kirim pesan via email di kitainformatika@gmail.com atau via WA di 087750503014. Jika mood penulis lagi baik, biasanya fast respon.
Comment Author Avatar
October 5, 2018 at 4:37 AM Delete
Contennya sangat bermanfaat tks brother