Saturday, October 14, 2017

Median Filter Untuk Citra RGB

Pendahuluan

Pada materi sebelumnya, kita sudah menerapkan Median Filter untuk citra gray. Tujuan utama menggunakan citra gray adalah sebagai image pre-processing dan bukan sekedar visualisasi saja (sebagai citra yang dinikmati manusia). Image pre-processing digunakan untuk menyiapkan citra sebelum diolah atau diambil informasinya. Salah satu tahapan image pre-processing adalah adalah noise reduction. Beberapa teknik pengolahan citra dan pengenalan pola, menggunakan citra gray (abu-abu) dalam prosesnya. Salah satu alasannya adalah tingginya komputasi yang diperlukan jika menggunakan citra RGB (warna). Citra berwarna dengan salt noise effect ditunjukkan pada Gambar 1 sebagai berikut:

Gambar 1. Citra RGB dengan Salt Noise Effect




Pengurangan noise menggunakan Median Filter juga bisa diterapkan pada citra berwarna dengan memodifikasi tulisan saya sebelumnya. Saya tidak banyak menyoroti teknis bagaimana algoritma maupun script yang digunakan untuk menerapkan Median Filter pada citra RGB, tetapi saya lebih senang mengamati waktu yang diperlukan untuk mengurangi noise di citra berwarna dibandingkan dengan citra abu-abu.

Metode Pengujian
Pada bagian ini, kita akan menyepakati bagaimana proses perhitungan waktu eksekusi metode Median Filter pada Citra RGB dan Citra Gray. Diagram alir untuk proses perhitungan waktunya ditunjukkan pada gambar 2 sebagai berikut:


Gambar 2. Skema Pengujian


Listing Program

Pada bagian berikut, saya langsung tulis script Median Filter dengan penambahan fitur pencatat waku eksekusi.

<?php
//Catat waktu mulainya
$time_start = microtime(true);

// Tentukan citra yang akan diolah
$gambar_awal = "salt_noise.jpg";

// pembentukan citra digital
$gambar_digital = imagecreatefromjpeg($gambar_awal);

// mencari dimensi gambar
$data_gambar = getimagesize($gambar_awal);


//Menyiapkan kanvas untuk citra baru
$akhir = imagecreatetruecolor($data_gambar[0],$data_gambar[1]);

// Proses semua piksel
for($x=1;$x<$data_gambar[0]-1;$x++){
    for($y=1;$y<$data_gambar[1]-1;$y++){
    
// Hitung semua nilai RGB di sekitar piksel yang discan  
  $red_a = red(imagecolorat($gambar_digital,$x,$y-1));
  $red_b = red(imagecolorat($gambar_digital, $x, $y+1));
  $red_c = red(imagecolorat($gambar_digital,$x-1,$y));
  $red_d = red(imagecolorat($gambar_digital, $x+1, $y));
  $red_e = red(imagecolorat($gambar_digital,$x-1, $y-1));
  $red_f = red(imagecolorat($gambar_digital, $x+1, $y-1));
  $red_g = red(imagecolorat($gambar_digital,$x-1, $y+1));
  $red_h = red(imagecolorat($gambar_digital, $x+1, $y+1));
  $med_red = median($red_a,$red_b,$red_c,$red_d,$red_e,$red_f,$red_g,$red_h);

  $green_a = green(imagecolorat($gambar_digital,$x,$y-1));
  $green_b = green(imagecolorat($gambar_digital, $x, $y+1));
  $green_c = green(imagecolorat($gambar_digital,$x-1,$y));
  $green_d = green(imagecolorat($gambar_digital, $x+1, $y));
  $green_e = green(imagecolorat($gambar_digital,$x-1, $y-1));
  $green_f = green(imagecolorat($gambar_digital, $x+1, $y-1));
  $green_g = green(imagecolorat($gambar_digital,$x-1, $y+1));
  $green_h = green(imagecolorat($gambar_digital, $x+1, $y+1));
  $med_green = median($green_a,$green_b,$green_c,$green_d,$green_e,$green_f,$green_g,$green_h);

  $blue_a = blue(imagecolorat($gambar_digital,$x,$y-1));
  $blue_b = blue(imagecolorat($gambar_digital, $x, $y+1));
  $blue_c = blue(imagecolorat($gambar_digital,$x-1,$y));
  $blue_d = blue(imagecolorat($gambar_digital, $x+1, $y));
  $blue_e = blue(imagecolorat($gambar_digital,$x-1, $y-1));
  $blue_f = blue(imagecolorat($gambar_digital, $x+1, $y-1));
  $blue_g = blue(imagecolorat($gambar_digital,$x-1, $y+1));
  $blue_h = blue(imagecolorat($gambar_digital, $x+1, $y+1));
  $med_blue = median($blue_a,$blue_b,$blue_c,$blue_d,$blue_e,$blue_f,$blue_g,$blue_h);
  
//menempatkan nilai median pada kanvas
 $color_new=imagecolorallocate($akhir,$med_red,$med_green,$med_blue);
 imagesetpixel($akhir,$x,$y,$color_new);          
  }
}

// Tampilkan Citra lama dan citra baru
imagejpeg($akhir, 'salt_noise2.jpg', 100);
echo "<img src=salt_noise.jpg>";
echo "<img src=salt_noise2.jpg>";

//Catat waktu selesai
$time_end = microtime(true);

//Hitung lama waktu eksekusinya
$time = $time_end - $time_start ;
echo '<p>Waktu eksekusi = ' . $time . ' seconds' ;


function red($pixel){
    $pixel = sprintf('%06x',$pixel);
    $red = hexdec(substr($pixel,0,2));
    return $red;
}

function green($pixel){
    $pixel = sprintf('%06x',$pixel);
    $green = hexdec(substr($pixel,2,2));
    return $green;
}

function blue($pixel){
    $pixel = sprintf('%06x',$pixel);
    $blue = hexdec(substr($pixel,4));
    return $blue;
}

function median($a,$b,$c,$d,$e,$f,$g,$h) {
    $nilai_tetangga = array($a,$b,$c,$d,$e,$f,$g,$h);
    sort($nilai_tetangga);
    $bawah = $nilai_tetangga[3];
    $atas = $nilai_tetangga[4];
    $abu_abu = floor(($bawah+$atas)/2);
    return $abu_abu;
}

?>
 
Hasil Percobaan
 
Berikut adalah Citra Gray yang telah dibersihkan noisenya menggunakan Median Filter beserta waktu eksekusinya.

Data Uji
  1. Nama: salt_noise.jpg
  2. Dimension: 480 x 361 pixel
  3. Size: 80.050 bytes
Gambar 3 Pengolahan Citra Gray

Gambar 4. Pengolahan Citra RGB

Gambar 5. Hasil Pengujian

Kesimpulan

Pengolahan Citra RGB memiliki rata-rata waktu lebih lama dibandingkan Citra Gray.


Semoga Bermanfaat
 

Tuesday, October 10, 2017

Image Enhancement dengan Median Filter

Pendahuluan

Median Filter adalah salah satu teknik dalam pengolahan citra pada domain spasial yang dapat digunakan untuk peningkatan kualitas citra (image enhancement) terutama mengurangi noise (distorsi) pada sebuah citra.
Sering kalanya citra yang akan kita proses memiliki kualitas yang kurang baik sehingga menyulitkan dalam proses pengolahan dan dapat berakibat sulitnya mengenali informasi dalam citra tersebut (pattern recognition). Kekurangbaikan citra tersebut bisa diakibatkan banyaknya informasi gangguan (noise) yang muncul pada sebuah gambar yang harus dikurangi terlebih dulu.
Contoh kualitas citra yang kurang baik.

Gambar 1. Gambar Dengan Banyak Noise

Domain spasial merupakan salah satu domain pengolahan citra yang memanipulasi sekumpulan picture element (pixel) dari sebuah citra sehingga menghasilkan nilai baru. Sekumpulan pixel yang dimaksud adalah 8 pixel tetangga dari pixel yang akan diproses. Ke-8 pixel tetangga ditunjukkan pada Gambar 2 sebagai berikut:
Gambar 2. Delapan Pixel Tetangga

Pixel tengah (x,y) akan diolah (manipulated) menggunakan 8 nilai tetangga pada domain 3x3. Nilai baru yang akan muncul "diakui" sebagai nilai baru yang menggantikan nilai asli sehingga diharapkan diperolehnya sebuah nilai pixel yang "menyerupai" nilai tetangganya dan pada akhirnya dapat meningkatkan kualitas citra.

Algoritma

Proses manipulasi pixel tengah dilakukan dengan mencari nilai tengah (median) dari 8 titik pixel di sekitarnya. Diagram alir untuk mencari nilai median dari 8 pixel tetangga ditunjukkan Gambar 3 sebagai berikut:


Gambar 3. Diagram Alir Mencari Nilai Median

Fungsi PHP untuk mengambil nilai abu-abu adalah sebagai berikut:

function gray($pixel){
    $pixel = sprintf('%06x',$pixel);
    $red = hexdec(substr($pixel,0,2))*0.30;
    $green = hexdec(substr($pixel,2,2))*0.59;
    $blue = hexdec(substr($pixel,4))*0.11;
    return $red+$green+$blue;
}

fungsi PHP untuk mencari median adalah sebagai berikut:
function mencari_median($a,$b,$c,$d,$e,$f,$g,$h) {
    $nilai_tetangga = array($a,$b,$c,$d,$e,$f,$g,$h);
    sort($nilai_tetangga);
    $bawah = $nilai_tetangga[3];
    $atas = $nilai_tetangga[4];
    $abu_abu = floor(($bawah+$atas)/2);
    return $abu_abu;
}

dimana nilai $a, $b, $c, $d, $e, $f, $g, $h adalah nilai gray (abu-abu) pada pixel (x-1,y+1), (x,y+1), (x+1,y+1), (x-1,y), (x+1,y), (x-1,y-1), (x,y-1), (x+1,y-1) pada Gambar 2. Nilai yang di-return pada fungsi ini menggantikan nilai pixel abu-abu pada koordinat (x,y). Lakukan proses ini untuk semua pixel pada citra. Diagram alir keseluruhan Median Filter ditunjukkan pada Gambar 4 sebagai berikut:


Gambar 4. Diagram Alir Median Filter Pengolahan Citra


Listing Program
Setelah kita pahami proses median filter pada penjelasan di atas, saatnya menulis kode program. Kode program untuk median filter adalah sebagai berikut:

<?php

// Tentukan citra yang akan diolah
$gambar_awal = "lena.jpg";

// pembentukan citra digital
$gambar_digital = imagecreatefromjpeg($gambar_awal);

// mencari dimensi gambar
$data_gambar = getimagesize($gambar_awal);

//Menyiapkan kanvas untuk citra baru
$akhir = imagecreatetruecolor($data_gambar[0],$data_gambar[1]);

// Proses semua piksel
for($x=1;$x<$data_gambar[0]-1;$x++){
    for($y=1;$y<$data_gambar[1]-1;$y++){
    
    // Hitung semua nilai abu-abu di sekitar piksel yang discan   
    $a = gray(imagecolorat($gambar_digital,$x,$y-1));
    $b = gray(imagecolorat($gambar_digital, $x, $y+1));
    $c = gray(imagecolorat($gambar_digital,$x-1,$y));
    $d = gray(imagecolorat($gambar_digital, $x+1, $y));
    $e = gray(imagecolorat($gambar_digital,$x-1, $y-1));
    $f = gray(imagecolorat($gambar_digital, $x+1, $y-1));
    $g = gray(imagecolorat($gambar_digital,$x-1, $y+1));
    $h = gray(imagecolorat($gambar_digital, $x+1, $y+1));
       
    //menghitung median 
    $abu_abu = mencari_median($a,$b,$c,$d,$e,$f,$g,$h);

    //tanam nilai abu-abu tersebut pada kanvas yang sudah kita siapkan
    $abu_new=imagecolorallocate($akhir,$abu_abu,$abu_abu,$abu_abu);
    imagesetpixel($akhir,$x,$y,$abu_new);           
  }
}

// Tampilkan Citra lama dan citra baru
imagejpeg($akhir, 'bagus.jpg', 100);
echo "<img src=lena.jpg>";
echo "<img src=bagus.jpg>";

function gray($pixel){
    $pixel = sprintf('%06x',$pixel);
    $red = hexdec(substr($pixel,0,2))*0.30;
    $green = hexdec(substr($pixel,2,2))*0.59;
    $blue = hexdec(substr($pixel,4))*0.11;
    return $red+$green+$blue;
}

function mencari_median($a,$b,$c,$d,$e,$f,$g,$h) {
    $nilai_tetangga = array($a,$b,$c,$d,$e,$f,$g,$h);
    sort($nilai_tetangga);
    $bawah = $nilai_tetangga[3];
    $atas = $nilai_tetangga[4];
    $abu_abu = floor(($bawah+$atas)/2);
    return $abu_abu;
}

?>

Hasil

 Gambar 5. Hasil Median Filter 1x

Jika proses ini diulang akan menghasilkan hasil seperti ditunjukkan pada gambar 6 sebagai berikut.
Gambar 6. Proses Median Filter 2x dan 3x

Bagaimana dengan Citra RGB beserta perbandingan waktu eksekusi antara Citra Gray dengan Citra RGB akan dijelaskan apda meteri berikutnya.

Semoga Bermanfaat. Selamat Mencoba..

Sunday, May 14, 2017

Komputasi Numeris: Metode Setengah Interval (Bisection Method).

Pendahuluan

Walaupun primitif dan merupakan metode dengan segala keterbatasan yang ada, metode setengah interval adalah metode paling sederhana dan paling mudah untuk dipahami sehingga cocok sebagai pembelajaran awal mata kuliah "Komputasi/ Metode Numeris". Kesederhanaan yang penulis maksud adalah kemudahan untuk menjelaskan istilah "interval" yang nanti akan kita gunakan pada metode secant pada pembahasan berikutnya. Metode ini metode iteratif yang digunakan untuk mencari akar persamaan (linier maupun non-linear) yang memiliki akar real.

Dasar Teori

1. Menentukan area awal

Metode setengah interval dimulai dari menentukan area (interval) awal sedemikian rupa sehingga, interval tsb mengapit akar pesamaan yang akan kita cari.
Gambar 1: Penentuan Area Awal
 
Ini kesulitan pertama metode setengah interval. Area awal yang dipilih HARUS mengapit akar yang akan dicari. Cara paling mudah adalah menentukan area awal, selebar-lebarnya, tapi ini akan berakibat pada jumlah iterasi yang semakin banyak.

Okay sementara, abaikan jumlah iterasi yang banyak tersebut, yang penting, ketemu dulu akarnya. :)

2. Membagi dua area.

Setelah interval awal kita tentukan, berikutnya, kita bagi area tersebut menjadi dua (red: inilah yang menyebabkan metode ini disebut metode setengah interval) sehingga grafiknya menjadi seperti berikut:

Gambar 2: Pembagian Dua Area

Proses ini mudah, tinggal jumlahkan nilai X1 dan X3 kemudian dibagi 2. Dapatlah nilai X2.

3. Membuang area yang tidak diperlukan.

Bagian ini sedikit sulit. Jika kita melihat grafik, mungkin tidak sulit bagi kita untuk menentukan bahwa area yang akan dibuang adalah area antara X1 s.d. X2. Tapi bagaimana jika dilakukan menggunakan program?

Untuk membuang daerah yang tidak diperlukan kita bisa memasukkan nilai X1, X2 dan X3 pada persamaan yang akan kita cari yaitu f(X1), f(X2) dan f(X3) seperti terlihat pada gambar berikut:

Gambar 3: Penentuan Titik-Titik Fungsi

Setelah kita tentukan, nilai f(X1), f(X2) dan f(X3), berikutnya kita "pilih" yang mana dari nilai X1 atu X3 yang akan kita "replace" dengan X2. Kata me-replace di sini artinya dibuang.

Caranya?

Kita pilih di antara X1 dan X3 yang memiliki tanda yang sama dengan X2. Sama-sama positif atau sama-sama negatif. Menentukannya mana di antara X1 dan X3 yang memiliki tanda yang sama dengan X2, cukup kalikan saja f(X1) dengan f(X2). Jika menghasilkan nilai positif ( > 0 ) maka f(X1) memiliki tanda yang sama dengan f(X2). Ini sesuai kodrat alam yang mengatakan:

"Jika dua bilangan dikalikan menghasilkan bilangan positif, maka kedua bilangan tersebut sama tandanya dan jika negatif maka kedua bilangan tersebut berbeda tanda"

 Sehingga grafik di atas menjadi:

Gambar 4: Area Setelah Dibagi Dua.

4. Mencari Error

Kata orang, mencari kesalahan adalah usaha paling mudah. Apalagi "kesalahan orang lain". Di sinipun, mencari kesalahan bisa menggunakan beberapa cara. Misalnya:
  • Mencari selisih antara X2 dengan nilai X2 sebelumnya.
  • Selisih antara nilai mutlak f(X2) dengan 0
Saya menggunakan cara yang kedua.

Apabila selisih antara f(X2) dengan 0 sudah lebih kecil dari toleransi error yang diberikan, maka selesailah sudah. Nilai X2 itulah yang menjadi akar persamaan. Jika belum, ulangi langkah 2.

5. Hasil akhir

Proses lengkap dari metode bisection ini digambarkan sebagai berikut:

Gambar 5. Iterasi Bisection


Algoritma Metode Bisection

Setelah kita paham metode bisection, saatnya kita tulis algoritma sederhananya (dulu).
  1. Tentukan nilai awal X1 dan X3, toleransi_error=0.0001, f(X2) = 1 dan jumlah_langkah = 0.
  2. Ketika f(X2) > toleransi error:
  3. Cari X2 = (X1 + X3) / 2  
  4. Cari f(X1) dan f(X2)
  5. Jika (f(X1) * f(X2)) > 0
  6. X1 = X2
  7. Jika tidak, X3 = X2
  8. Cari nilai mutlak f(X2) = | f(X2)|
  9. Loop ke langkah 2.
  10. Tampilkan hasil persamaan = X2.
  11. Selesai
Algoritma di atas, adalah algoritma sederhana dari metode bisection. Silahkan improvisasi sendiri untuk anomali-anomali yang ada.

  • Nilai X1 dan X3 ternyata tidak mengapit akar persamaan yang dicari
  • Ada lebih dari satu akar pada arena X1 dan X3 yang ditentukan.
Listing program:

Asumsikan persamaan yang akan kita cari adalah: f(x) = x^2 - x - 6 dimana akar yang akan kita peroleh seharusnya 3 dan -2.

#include <iostream>
using namespace std;

void main() {

    float x1,x2,x3,fx1,fx2,fx3,toleransi_error;
    int iterasi;

    cout << "Masukkan Nilai X1 : ";
    cin >> x1;
    cout << "Masukkan Nilai X3 : ";
    cin >> x3;

    toleransi_error=1;
    iterasi=0;
   
    while (toleransi_error > 0.00001)
    {
        iterasi++;
        fx1 = (x1 * x1) - x1 - 6;
        fx3 = (x3 * x3) - x3 - 6;

        x2 = (x1 + x3) / 2;
        fx2 = (x2 * x2) - x2 - 6;

        if ((fx1 * fx2) > 0)
            x1 = x2;
        else
            x3 = x2;

        if (fx2 < 0)
            toleransi_error = fx2 * -1;
        else
            toleransi_error = fx2;

    }

    cout << "Jumlah iterasi : " << iterasi << endl;
    cout << "Akar persamaan : " << x2 <<endl;

    system ("pause");
}


Testing Program

Setelah kita tulis kode program, saatnya kita jalankan program sederhana tersebut.


 
Gambar 6: Output Program

Ingat, contoh di atas adalah penerapan metode bisection paling sederhana dengan mengabaikan anomali-anomali yang ada. Silahkan di-improvisasi sendiri untuk anomali-anomali tersebut.

Versi Excel

Berikut angka-angka metode bisection jika ditulis menggunakan MS Excel:

Silahkan unduh versi excelnya di sini.

Selamat mencoba.