Implementasi Algoritma Difusi Non-linier Untuk Penghalusan Citra

Awalnya saya ingin menunda untuk menulis ini karena belum mendapatkan informasi yang cukup untuk diacu karena kebanyakan masih pemahaman pribadi yang subjektif. Tetapi akhirnya saya tulis juga dengan alasan sekedar menceritakan hal-hal yang saya capai baru-baru ini (supaya tidak lupa).

Utak-atik kali ini didasarkan pada rasa penasaran Saya ketika membaca Buku Digital Image Processing khsususnya pada bagian model regularisasi atau variasional. Disebabkan dasar matematika (khususnya kalkulus multivariabel dan aljabar linier lanjutan) saya yang agak lemah. Saya jadi lambat mencerna isi dari buku tersebut. Selama ini operasi-operasi pengolahan citra yang saya buat implementasinya hanya dalam domain spasial. Untuk operasi dalam domain frekuensi sengaja saya tunda karena saya sendiri belum paham untuk mengimplementasi algoritma Transformasi Fourier (FFT) sendiri. Kode untuk melakukan FFT sebenarnya sudah banyak tersedia. Persoalannya adalah karena tujuan saya untuk belajar maka sebisa mungkin saya paham dulu teori dan prinsip algoritmanya baru nanti mungkin saya mulai ngoprek pengolahan citra dalam domain ini (domain wavelet kapan yah?).

Kembali lagi ke masalah difusi non-linier (non-linear diffusion) akhirnya saya kembali merujuk ke wikipedia dan om google untuk mempelajari lagi tentang difusi dan teori-teori yang terkait di berbagai bidang ilmu(matematika, fisika, dan biologi). Akhirnya setelah memaksa otak untuk mencerna prinsip dari proses difusi, saya mendapatkan ide untuk membuat implementasinya secara sederhana. Prinsipnya sederhana, berdasarkan teori difusi yang saya pahami seperti berikut

partikel-partikel dalam area berkonsentrasi tinggi akan bergerak menuju area dengan konsentrasi yang lebih rendah

Berdasarkan prinsip di atas saya memodelkan setiap pixel sebagai sebuah area. Intensitas pixel tersebut merupakan akibat dari akumulasi (banyaknya) partikel yang terakumulasi pada area tersebut. Asumsi saya proses difusi merupakan proses yang mempertahankan volum. Maka saya bisa membuat algoritma difusi dengan menggerakkan partikel dalam suatu area ke area lain yang terhubung (bertetangga). Sederhananya, ini hanya masalah mengurangi intensitas di suatu pixel sebesar delta dan menambahkan pixel lain di tetangganya sebesar delta juga. Konsentrasi diibaratkan intensitas.

Proses pemindahan intensitas tiap pixel tersebut dilakukan secara iteratif. Lama-kelamaan gambar pada citra akan nampak kabur. Sampai saat ini yang dilakukan baru difusi yang menurut saya linier dalam artian setiap pixel akan diproses tanpa mempertimbangkan pentingnya suatu pixel dalam mengandung informasi.

Implementasi Algoritma Difusi Linier dalam delphi

Potongan kode berikut mencoba untuk melakukan difusi linier untuk citra greyscale.

procedure TFrmMain.Diffuse1Execute(Sender: TObject);
{ Kamus }
const dir : array[0..7] of TPoint = (
	(X:0;Y:-1),//UP
	(X:1;Y:-1),                     
	(X:1;Y:0),//RIGHT
	(X:1;Y:1),
	(X:0;Y:1),//DOWN
	(X:-1;Y:1),
	(X:-1;Y:0),//LEFT
	(X:-1;Y:-1)
	);
var
	b : TBitmap;
	p : array of PArrRGB;
	cl : array of integer;
	icl : array of integer;
	j, i, k, l : integer;
	minidx, mindir, amount : integer;
	iter : integer;
        
	function is_ok(x, y : integer): boolean;
	begin result := (x>=0) and (x<b.Width) and (y>=0) and (y<b.Height); end;

{ Algoritma }
begin
	b := citra_clone(Image1.Picture.Bitmap);
	setlength(p, b.Height);
	for j := 0 to b.Height-1 do p[j] := b.ScanLine[j];
        
	for iter := 0 to 10 do begin
        
	for j := 0 to b.Height-1 do begin
		for i := 0 to b.Width-1 do begin
        
			{ lihat pixel di sekitar p_current }
			setlength(cl, 0);
			setlength(icl, 0);
			for l := 0 to high(dir) do begin
				if is_ok(i+dir[l].X, j+dir[l].Y) then begin
					setlength(cl, length(cl)+1);
					cl[high(cl)] := p[j+dir[l].Y][i+dir[l].X].r;
					setlength(icl, length(icl)+1);
					icl[high(icl)] := l;
				end;
			end;
                
			{ cari pixel tetangga p_dest dengan konsentrasi terrendah }
			minidx := 0;
			mindir := icl[0];
			if length(cl)>0 then begin
				for l := 1 to high(icl) do
					if cl[l] > cl[minidx] then begin
						minidx := l;
						mindir := icl[l];
					end;
					
				{ pindahkan warna dari current pixel ke p_dest }
				: linear diffusion
				sedemikian sehingga nilai current pixel sama dengan nilai p_dest
				
				k := (cl[minidx] + p[j][i].r) shr 1;
				p[j][i] := warna_create(k, k, k);
				p[j+dir[mindir].Y][i+dir[mindir].X] := p[j][i];
			end;
        
			end;
		end;
                
	end;                    

	FrmImg.Preview(b, true);
	Image1.Picture.Bitmap.Assign(b);
	Image1.Refresh;
	b.Free;
end;

Difusi Non-linier

Difusi yang bersifat non-linier dicapai dengan menggunakan faktor penskalaan pada jumlah intensitas pixel yang dipindahkan. faktor penskalaan ini bisa didapat menggunakan nilai fitur tepi (edge). Untuk setiap iterasi, citra yang mengandung fitur tepi dihitung ulang. Pixel yang merupakan bagian dari tepi maka intensitas tepinya besar sehingga koefisien skala pemindahannya menjadi kecil.

Implementasi Algoritma Difusi Non-linier dalam delphi

procedure TFrmMain.Diffuse1Execute(Sender: TObject);
{ Kamus }
const dir : array[0..7] of TPoint = (
	(X:0;Y:-1),//UP
	(X:1;Y:-1),                     
	(X:1;Y:0),//RIGHT
	(X:1;Y:1),
	(X:0;Y:1),//DOWN
	(X:-1;Y:1),
	(X:-1;Y:0),//LEFT
	(X:-1;Y:-1)
	);
var
	b : TBitmap;
	bgrey : TBitmap;
	bref : TBitmap;
	p, pref , pgrey : array of PArrRGB;
	cl : array of integer;
	icl : array of integer;
	j, i, k, l : integer;
	minidx, mindir, amount : integer;
	rmov, gmov, bmov : integer;
	diffuse_coeff : real;
	iter : integer;
        
	function is_ok(x, y : integer): boolean;
	begin result := (x>=0) and (x<b.Width) and (y>=0) and (y<b.Height); end;

{ Algoritma }
begin
	b := citra_clone(Image1.Picture.Bitmap);
	setlength(p, b.Height);
	for j := 0 to b.Height-1 do p[j] := b.ScanLine[j];
        
	for iter := 0 to 10 do begin
        
	bgrey := citra_make_greyscale(b);
	bref := citra_filter_mean(bgrey, KLAPLACIANOFGAUSSIAN);
        
	setlength(pref, bref.Height);
	for j := 0 to bref.Height-1 do pref[j] := bref.ScanLine[j];
	setlength(pgrey, bgrey.Height);
	for j := 0 to bgrey.Height-1 do pgrey[j] := bgrey.ScanLine[j];
        
	for j := 0 to b.Height-1 do begin
		for i := 0 to b.Width-1 do begin
        
			{ lihat pixel di sekitar p_current }
			setlength(cl, 0);
			setlength(icl, 0);
			for l := 0 to high(dir) do begin
				if is_ok(i+dir[l].X, j+dir[l].Y) then begin
					setlength(cl, length(cl)+1);
					cl[high(cl)] := pgrey[j+dir[l].Y][i+dir[l].X].r;
					setlength(icl, length(icl)+1);
					icl[high(icl)] := l;
				end;
			end;
                
			{ cari pixel tetangga p_dest dengan konsentrasi terrendah }
			minidx := 0;
			mindir := icl[0];
			if length(cl)>0 then begin
				for l := 1 to high(icl) do
					if cl[l] > cl[minidx] then begin
						minidx := l;
						mindir := icl[l];
					end;
					
				{ pindahkan warna dari current pixel ke p_dest }
				{ : non-linear diffusion }
				{ sebesar amount = diffuse_coeff * current_pixel }
				{ diffuse_coeff := 1 - edge_profile current pixel }
				if pref[j][i].r < 80 then begin
					diffuse_coeff := (255 - pref[j][i].r) / 255;                    
                        
					rmov := clamp(round(diffuse_coeff * ((p[j][i].r-p[j+dir[mindir].Y][i+dir[mindir].X].r) shr 1)));
					gmov := clamp(round(diffuse_coeff * ((p[j][i].g-p[j+dir[mindir].Y][i+dir[mindir].X].g) shr 1)));
					bmov := clamp(round(diffuse_coeff * ((p[j][i].b-p[j+dir[mindir].Y][i+dir[mindir].X].b) shr 1)));

					with p[j][i] do begin
						r := r - rmov;
						g := g - gmov;
						b := b - bmov;
					end;
                        
					with p[j+dir[mindir].Y][i+dir[mindir].X] do begin
						r := r + rmov;
						g := g + gmov;
						b := b + bmov;
					end;
				end;
			
			end;
        
		end;
	end;
                
	bref.free;
	bgrey.Free;                     
	end;                    

	FrmImg.Preview(b, true);
	Image1.Picture.Bitmap.Assign(b);
	Image1.Refresh;
	b.Free;
end;

Hasil Pengujian

Gambar Asli

Gbr 1. Foto sebelum smoothing

peb-jonas-3-smooth.jpg

Gbr 2. Foto sesudah smoothing

i00045-original.jpg

Gbr 1. Foto sebelum smoothing

i00045-smooth.jpg

Gbr 2. Foto sesudah smoothing

9 comments

  1. yadi · Oktober 26, 2007

    wah…ternyata banyak ya metode penghalusan citra…
    mana ya yang lebih baik sama metode median…
    eh..mas peb..itu fotonya mas peb ya..
    hmmm sama sapa ya..he2..

  2. Intan · Mei 10, 2008

    waa.. bisa minta programnya yg difusi non linier ini secara utuh nggak? kalo boleh minta kirim ke emailku ya.. thx.. soalnya ini ada tgs kul disuru cari macam2 algoritma untuk makul PCD, thanks2 so much ya..

  3. pebbie · Mei 13, 2008

    @intan: kan sudah dikasi source-codenya di tulisan di atas?

  4. mahasiswa · Mei 15, 2008

    mas, tolong tanya fungsi-fungsi ini source code nya bagaimana? dan nilai kembalinya apa?
    citra_filter_mean(bgrey, KLAPLACIANOFGAUSSIAN);
    high(dir)
    clamp(int x)

    klo bs sekalian jelaskan maksudnya, terima kasih byk

  5. pebbie · Mei 15, 2008

    citra_filter_mean : konvolusi 2D, maksud fungsi itu (dalam konteks kode di atas) adalah menghasilkan citra yang berisi kekuatan edge (fitur citra yang harus dipertahankan).

    high(dir) : menghasilkan indeks maksimum dari array dir

    clamp(x) : int -> int
    | x max = max
    | true = x

    maksudnya : menjamin nilai kembalian fungsi agar ada dalam jangkauan min <= x <= max

  6. sardi · Agustus 18, 2009

    bisa kirim artikel ato tulisan gt tentang apa tu difusi linier ma non linier sekaligus rumus2 gt cz da tugas ni dari dosen soalnya saya cari di internet gak da yang bahasa indonesianya.tolong ya…..kirim ke email saya

  7. tian · Desember 13, 2010

    mas ad ide tentang tugas pencitraan yang gampang dipelajari

  8. kurnia · Desember 13, 2010

    mas ada saran atau ide untuk tugas smoothing citra

  9. kurnia · Desember 13, 2010

    bisa bantu ide tugas citra

Tinggalkan Balasan

Isikan data di bawah atau klik salah satu ikon untuk log in:

Logo WordPress.com

You are commenting using your WordPress.com account. Logout / Ubah )

Gambar Twitter

You are commenting using your Twitter account. Logout / Ubah )

Foto Facebook

You are commenting using your Facebook account. Logout / Ubah )

Foto Google+

You are commenting using your Google+ account. Logout / Ubah )

Connecting to %s