Implementasi Content Based Image Retrieval Menggunakan Speeded-Up Robust Features (SURF)

A-1

Listing Program
1. MainWindow.cs
using System;
using System.Windows;
namespace SkripsiTepe
{
public partial class MainWindow : Window
{
public MainWindow()
{
InitializeComponent();
}
void btnstart_Click(object sender, System.Windows.RoutedEventArgs e)
{
MainSearchWindow win = new MainSearchWindow();
win.Show();
}
void btnhelp_Click(object sender, RoutedEventArgs e)
{

HelpWindow win2 = new HelpWindow();
win2.Show();
}
}
}

2. MainSearchWindow.cs
using SkripsiTepe.DTOs;
using SkripsiTepe.Helper;
using SkripsiTepe.Indexers;
using SkripsiTepe.Query;
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Diagnostics;
using System.IO;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Media.Imaging;


namespace SkripsiTepe
{
public partial class MainSearchWindow : Window

Universitas Sumatera Utara

A-2

{
private const string host = "localhost";
public bool ExecInParallel { get; set; }
public string IndexDirectory { get; set; }
public string QueryImageFullPath { get; set; }
public emAlgo SelectedAlgo { get; set; }
private BackgroundWorker IndexBgWorker;
private BackgroundWorker QueryBgWorker;
private Stopwatch _stopWatch;
public MainSearchWindow()
{
InitializeComponent();

}
private void frmMainSearch_Loaded(object sender, RoutedEventArgs e)
{
InitIndexDirectory();
cmbAlgo.SelectedIndex = Properties.Settings.Default.SelectedAlgo;
SelectedAlgo = GetSelectedAlgo();
LoadSurfSettings();
SetBackgroundWorker();
}
private void LoadSurfSettings()
{
cmbSurfThreshold.SelectedIndex =
Properties.Settings.Default.SurfThresholdSelectedIndex;
cmbSurfApproach.SelectedIndex = Properties.Settings.Default.SurfAlgo;
}
private void InitIndexDirectory()
{
string indexDirecroty = Properties.Settings.Default.IndexFolder;
if (string.IsNullOrEmpty(indexDirecroty))
{

indexDirecroty = DirectoryHelper.PictureObserverDirectory; //helper
Properties.Settings.Default.IndexFolder = indexDirecroty;
}
SetIndexDirectory(indexDirecroty);
}
//002
private void SetIndexDirectory(string folder)
{
lblDirectoryPath.Text = folder;
IndexDirectory = folder;

Universitas Sumatera Utara

A-3

Properties.Settings.Default.IndexFolder = folder;
Properties.Settings.Default.Save();
}
//asynctask setting
private void SetBackgroundWorker()

{
IndexBgWorker = new BackgroundWorker();
IndexBgWorker.DoWork += new DoWorkEventHandler(IndexBgWorker_DoWork);
IndexBgWorker.ProgressChanged += new ProgressChangedEventHandler
(IndexBgWorker_ProgressChanged);
IndexBgWorker.RunWorkerCompleted += new RunWorkerCompletedEventHandler
(IndexBgWorker_RunWorkerCompleted);
IndexBgWorker.WorkerReportsProgress = true;
IndexBgWorker.WorkerSupportsCancellation = true;
QueryBgWorker = new BackgroundWorker();
QueryBgWorker.DoWork += new DoWorkEventHandler(QueryBgWorker_DoWork);
QueryBgWorker.RunWorkerCompleted += new RunWorkerCompletedEventHandler
(QueryBgWorker_RunWorkerCompleted);
QueryBgWorker.WorkerReportsProgress = true;
}
private void SaveSurfSettingValues()
{
this.Dispatcher.Invoke(() =>
{
Properties.Settings.Default.SurfThresholdSelectedIndex =

cmbSurfThreshold.SelectedIndex;
Properties.Settings.Default.SurfAlgo = cmbSurfApproach.SelectedIndex;
Properties.Settings.Default.Save();
});
}
private emAlgo GetSelectedAlgo()
{
emAlgo selectAlgo = emAlgo.Undetermined;
if (cmbAlgo.SelectedIndex > -1)
selectAlgo = (emAlgo)cmbAlgo.SelectedIndex + 1;
return selectAlgo;
}

public FileInfo[] getFiles(string SourceFolder, string Filter,
System.IO.SearchOption searchOption)
{
List files = new List();

Universitas Sumatera Utara


A-4

DirectoryInfo di = new DirectoryInfo(SourceFolder);
// Create an array of filter string
string[] MultipleFilters = Filter.Split('|');
// for each filter find mathing file names
foreach (string FileFilter in MultipleFilters)
{
// add found file names to array list
files.AddRange(di.GetFiles(FileFilter, searchOption));
}
// returns string array of relevant file names
return files.ToArray();
}
private SurfSettings GetSurfSetting()
{
SurfSettings surfSetting = new SurfSettings();
this.Dispatcher.Invoke(() =>
{
surfSetting.HessianThresh = Convert.ToDouble((cmbSurfThreshold.SelectedItem as

ListBoxItem).Content);
surfSetting.Algorithm = (SurfAlgo)cmbSurfApproach.SelectedIndex;
});
return surfSetting;
}
private void cmbAlgo_SelectionChanged(object sender,
System.Windows.Controls.SelectionChangedEventArgs e)
{
Properties.Settings.Default.SelectedAlgo = cmbAlgo.SelectedIndex;
Properties.Settings.Default.Save();
SelectedAlgo = GetSelectedAlgo();
if (SelectedAlgo == emAlgo.AccordSurf)
{
var selectedIndex = cmbSurfApproach.SelectedIndex;
(cmbSurfApproach.Items[1] as ListBoxItem).Content = "kd-tree";
cmbSurfApproach.SelectedIndex = -1;
cmbSurfApproach.SelectedIndex = selectedIndex;
}
}


#region Indexing Section
//001 - Pilih Folder
private void btnSelectFolder_Click(object sender, RoutedEventArgs e)
{

Universitas Sumatera Utara

A-5

string _folderName = IndexDirectory;
var dlg1 = new FolderBrowserDialogEx //helper
{
Description = "Select a folder for the extracted files:",
ShowNewFolderButton = false,
ShowEditBox = true,
SelectedPath = _folderName,
ShowFullPathInEditBox = false,
};
dlg1.RootFolder = System.Environment.SpecialFolder.MyComputer;
System.Windows.Forms.DialogResult result = dlg1.ShowDialog();

if (result == System.Windows.Forms.DialogResult.OK)
{
SetIndexDirectory(dlg1.SelectedPath);
}
}
//003
private void btnIndex_Click(object sender, RoutedEventArgs e)
{
btnIndex.IsEnabled = false;
if (SelectedAlgo == emAlgo.AccordSurf)
{
//Save Settings
SaveSurfSettingValues();
//Pass Surf Settings
SurfSettings surfSetting = GetSurfSetting();
IndexBgWorker.RunWorkerAsync(surfSetting);
}
else
{
IndexBgWorker.RunWorkerAsync();

}
}
//004
private void IndexBgWorker_DoWork(object sender, DoWorkEventArgs e)
{
try
{
WriteIndexStatus("Indexing...");
SurfSettings surfSetting;
switch (SelectedAlgo)

Universitas Sumatera Utara

A-6

{
case emAlgo.Undetermined:
MessageBox.Show("Please select Algorithm for indexing");
return;
case emAlgo.AccordSurf:
surfSetting = (e.Argument as SurfSettings);
if (surfSetting == null)
{
MessageBox.Show("SurfSetting not supplied");
return;
};
AccordSurfAlgoIndexing(surfSetting);
break;
default:
MessageBox.Show("Pilih Algoritma");
return;
}
}
catch (Exception ex)
{
Debug.WriteLine(ex.ToString());
throw;
}
}
//004a
private void IndexBgWorker_ProgressChanged(object sender, ProgressChangedEventArgs
e)
{
pbIndex.Value = e.ProgressPercentage + 1;
}
//004b
private void IndexBgWorker_RunWorkerCompleted(object sender,
RunWorkerCompletedEventArgs e)
{
if (e.Error != null)
MessageBox.Show(e.Error.ToString());
btnIndex.IsEnabled = true;
}
private void WriteIndexStatus(string msg)
{
var txtdispatcher = lblIndexStatus.Dispatcher;
if (!txtdispatcher.CheckAccess())
{
txtdispatcher.Invoke((Action)(() => lblIndexStatus.Text = msg));
}

Universitas Sumatera Utara

A-7

else
{
lblIndexStatus.Text = msg;
}
}

//005
private void AccordSurfAlgoIndexing(SurfSettings surfSetting)
{
var imageFiles = getFiles(IndexDirectory, "*.gif|*.jpg|*.png|*.bmp|*.jpeg",
SearchOption.TopDirectoryOnly);
int totalFileCount = imageFiles.Length;
Dispatcher.Invoke((Action)delegate
{
pbIndex.Minimum = 0; pbIndex.Maximum = totalFileCount; lblIndexStatus.Text =
"Indexing..";
});
if (surfSetting.Algorithm == SurfAlgo.Linear)
{
SurfIndexer4 surfIndexer = new SurfIndexer4();
if (ExecInParallel)
surfIndexer.IndexFilesAsync(imageFiles, IndexBgWorker, WriteIndexStatus,
surfSetting);
else
surfIndexer.IndexFiles(imageFiles, IndexBgWorker, WriteIndexStatus, surfSetting);
}
}
#region Context Menu
private void brdImage_ContextMenuOpening(object sender, ContextMenuEventArgs e)
{
FrameworkElement fe = e.Source as FrameworkElement;
ContextMenu cm = fe.ContextMenu;
while (cm == null)
{
fe = (FrameworkElement)fe.Parent;
if (fe == null) break;
cm = fe.ContextMenu;
}
MenuItem openSurfDetails = null;
foreach (MenuItem mi in cm.Items)
{
if (mi.Name == "mnuOpenSurfDetail")
{

Universitas Sumatera Utara

A-8

openSurfDetails = mi;
}
}
if (SelectedAlgo == emAlgo.AccordSurf)
{
if (openSurfDetails != null) openSurfDetails.Visibility =
System.Windows.Visibility.Visible;
}
else
{
if (openSurfDetails != null) openSurfDetails.Visibility =
System.Windows.Visibility.Collapsed;
}
}
private void mnuOpenSurfDetail_Click(object sender, RoutedEventArgs e)
{
string selectedObserverImage = string.Empty;
string selectedModelImage = string.Empty;
MenuItem mnu = sender as MenuItem;
Border selectedBorder = null;
if (mnu != null)
{
selectedBorder = ((ContextMenu)mnu.Parent).PlacementTarget as Border;
selectedObserverImage = (string)selectedBorder.Tag;
}
selectedModelImage = QueryImageFullPath;
bool isObserverImagePathFound = !string.IsNullOrWhiteSpace(selectedObserverImage);
isObserverImagePathFound = isObserverImagePathFound &&
File.Exists(selectedObserverImage);
bool isModelImagePathFound = !string.IsNullOrWhiteSpace(selectedModelImage);
isModelImagePathFound = isObserverImagePathFound &&
File.Exists(selectedModelImage);

if (isObserverImagePathFound & isModelImagePathFound)
{
SurfSettings surfSetting = GetSurfSetting();
if (SelectedAlgo == emAlgo.AccordSurf)
{ //pindah windows
AccordSurfWindow win = new AccordSurfWindow(selectedModelImage,
selectedObserverImage, surfSetting);
win.Show();
}

Universitas Sumatera Utara

A-9

}
}
private void mnuOpenPic_Click(object sender, RoutedEventArgs e)
{
string selectedObserverImage = string.Empty;
string selectedModelImage = string.Empty;
MenuItem mnu = sender as MenuItem;
Border selectedBorder = null;
if (mnu != null)
{
selectedBorder = ((ContextMenu)mnu.Parent).PlacementTarget as Border;
selectedObserverImage = (string)selectedBorder.Tag;
}
selectedModelImage = QueryImageFullPath;
bool isObserverImagePathFound = !string.IsNullOrWhiteSpace(selectedObserverImage);
isObserverImagePathFound = isObserverImagePathFound &&
File.Exists(selectedObserverImage);
if (isObserverImagePathFound)
{
System.Diagnostics.Process.Start(selectedObserverImage);
}
}
#endregion
//006a
#region Pilih gambar dan cari
private void btnSelectQueryImage_Click(object sender, RoutedEventArgs e)
{
string queryImagePath = SelectQueryImage();
QueryImage(queryImagePath);
}
//006b
//ulangipencarian
private void btnQueryImage_Click(object sender, RoutedEventArgs e)
{
QueryImage(QueryImageFullPath);
}
//007
private string SelectQueryImage()
{
string queryImageFilePath = string.Empty;
Microsoft.Win32.OpenFileDialog dlg = new Microsoft.Win32.OpenFileDialog();

Universitas Sumatera Utara

A-10

if (string.IsNullOrWhiteSpace(Properties.Settings.Default.QueryFolder))
{
dlg.InitialDirectory = IndexDirectory;
}
else
{
dlg.InitialDirectory = Properties.Settings.Default.QueryFolder;
}

// Set filter for file extension and default file extension
dlg.DefaultExt = ".jpg";
dlg.Filter = "JPG Files (*.jpg)|*.jpg|JPEG Files (*.jpeg)|*.jpeg|PNG Files
(*.png)|*.png|JPG Files (*.jpg)|*.jpg|GIF Files (*.gif)|*.gif";

// Display OpenFileDialog by calling ShowDialog method
Nullable result = dlg.ShowDialog();

// Get the selected file name and display in a TextBox
if (result == true)
{
// Open document
queryImageFilePath = dlg.FileName;
txtQuery.Text = queryImageFilePath;
QueryImageFullPath = queryImageFilePath;
imqQuery.Source = new BitmapImage(new Uri(queryImageFilePath));
Properties.Settings.Default.QueryFolder =
Path.GetDirectoryName(queryImageFilePath);
Properties.Settings.Default.Save();
}
return queryImageFilePath;
}
//009
private void QueryBgWorker_DoWork(object sender, DoWorkEventArgs e)
{
this.Dispatcher.Invoke(() =>
{
btnSelectQueryImage.IsEnabled = false;
btnQueryImage.IsEnabled = false;
});
switch (SelectedAlgo)
{

Universitas Sumatera Utara

A-11

case emAlgo.AccordSurf:
QueryAccordSurfAlgo(QueryImageFullPath);
break;
default:
MessageBox.Show("Pilih Algoritma");
return;
}
this.Dispatcher.Invoke(() =>
{
btnSelectQueryImage.IsEnabled = true;
btnQueryImage.IsEnabled = true;
});
}

private void QueryBgWorker_RunWorkerCompleted(object sender,
RunWorkerCompletedEventArgs e)
{
if (e.Error != null)
{
MessageBox.Show(e.Error.ToString());
WriteQueryStatus("Error in querying! Couldn't query");
}
btnQueryImage.IsEnabled = true;
btnSelectQueryImage.IsEnabled = true;
}
//008
private void QueryImage(string queryImagePath)
{
try
{
ImageList.ItemsSource = null;
if (!string.IsNullOrEmpty(queryImagePath))
{
QueryImageFullPath = queryImagePath;
switch (SelectedAlgo)
{
case emAlgo.Undetermined:
MessageBox.Show("Pilih Algoritma");
return;

Universitas Sumatera Utara

A-12

case emAlgo.AccordSurf:
QueryBgWorker.RunWorkerAsync();
break;
default:
MessageBox.Show("Algoritma Error");
return;
}
}
}
catch (Exception ex)
{
MessageBox.Show(ex.ToString(), "Error", MessageBoxButton.OK,
MessageBoxImage.Error);
}
}
//010
private void QueryAccordSurfAlgo(string queryImagePath)
{
WriteQueryStatus("Retrieving...");
SaveSurfSettingValues();
//DTOs
List searchImage = new List();
SurfSettings surfSetting = GetSurfSetting();
string msg="";
if (surfSetting.Algorithm == SurfAlgo.Linear)
{
//Query
SurfQuery4 surfQuery = new SurfQuery4();
_stopWatch = Stopwatch.StartNew();
searchImage = surfQuery.QueryImage(queryImagePath, out msg, surfSetting);
_stopWatch.Stop();
}

msg += string.Format(" {0} ms", _stopWatch.ElapsedMilliseconds);
WriteQueryStatus(msg);
this.Dispatcher.Invoke(() =>
{
ImageList.ItemsSource = searchImage;
lblTotalCount.Text = searchImage.Count.ToString();
});
}

Universitas Sumatera Utara

A-13

private void WriteQueryStatus(string msg)
{
var txtdispatcher = lblQueryStatus.Dispatcher;
if (!txtdispatcher.CheckAccess())
{
txtdispatcher.Invoke((Action)(() => lblQueryStatus.Text = msg));
}
else
{
lblQueryStatus.Text = msg;
}
}
#endregion
private int GetNumberOfImageFilesInIndexDirectory()
{
FileInfo[] imageFiles = getFiles(IndexDirectory, "*.gif|*.jpg|*.png|*.bmp|*.jpeg",
SearchOption.TopDirectoryOnly);
int totalFileCount = imageFiles.Length;
return totalFileCount;
}
#endregion
}
}
3. SurfDetailWindow.cs
using System.Windows;
using System.Windows.Documents;
using SkripsiTepe.DTOs;
using System.Windows.Media.Imaging;
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Text;
using System.Diagnostics;
using System.IO;
using Gataulah;
namespace SkripsiTepe
{
///
/// Interaction logic for AccordSurf.xaml
///
public partial class AccordSurfWindow : Window
{

Universitas Sumatera Utara

A-14

Bitmap returnBitmap;
List ipts1 = new List();
List ipts2 = new List();
public string ModelImagePath { get; set; }
public string ObserverImagePath { get; set; }
public SurfSettings SurfSetting { get; set; }
public AccordSurfWindow()
{
InitializeComponent();
}
public AccordSurfWindow(string modelImagePath, string observerImagePath, SurfSettings
setting) : this()
{
this.ModelImagePath = modelImagePath;
this.ObserverImagePath = observerImagePath;
this.SurfSetting = setting;
}
private void AccordSurfCompareWin_Loaded(object sender, RoutedEventArgs e)
{
ShowImage();
}
protected void ShowImage()
{
bool isModelImageMissing = string.IsNullOrEmpty(ModelImagePath);
bool isObserverImageMissing = string.IsNullOrEmpty(ObserverImagePath);
if (isModelImageMissing || isObserverImageMissing)
return;
Bitmap compareImagebmp = CompareAndDrawImage(new Bitmap(ModelImagePath),
new Bitmap(ObserverImagePath),
SurfSetting);
if (compareImagebmp != null)
{
MemoryStream ms = new MemoryStream();
compareImagebmp.Save(ms, System.Drawing.Imaging.ImageFormat.Png);
ms.Position = 0;
BitmapImage bi = new BitmapImage();
bi.BeginInit();
bi.StreamSource = ms;
bi.EndInit();
imageAccordCompare.Source = bi;

Universitas Sumatera Utara

A-15

}
else
{
this.Close();
}
}
private Bitmap CompareAndDrawImage(Bitmap modelImage, Bitmap observedImage,
SurfSettings setting)
{
Stopwatch watch1 = new Stopwatch();
Stopwatch watch2 = new Stopwatch();

watch2.Start();
watch1.Reset(); watch1.Start();
double hessianThreshold = setting.HessianThresh.HasValue ?
setting.HessianThresh.Value : 500;
float hessianThreshold2 = (float)hessianThreshold / 1000000;

IntegralImage iimg1 = IntegralImage.FromImage(modelImage);
ipts1 = FastHessian.getIpoints(hessianThreshold2, 5, 2, iimg1);
SurfDescriptor.DecribeInterestPoints(ipts1, false, false, iimg1);
IntegralImage iimg2 = IntegralImage.FromImage(observedImage);
ipts2 = FastHessian.getIpoints(hessianThreshold2, 5, 2, iimg2);
SurfDescriptor.DecribeInterestPoints(ipts2, false, false, iimg2);
watch1.Stop();
Debug.WriteLine("Surf Detection tooked {0} ms", watch1.ElapsedMilliseconds);

List[] matches = Utils.getMatches(ipts1, ipts2);
if (ipts1.Count < 4 || ipts2.Count< 4)
{
MessageBox.Show("Error, Interest Point tidak cukup");
return null;
}
PaintSURF(modelImage,observedImage, matches);
return returnBitmap;

Universitas Sumatera Utara

A-16

}
private void PaintSURF(Bitmap img1, Bitmap img2, List[] matches)
{
Bitmap bmp = new Bitmap(img1.Width + img2.Width, Math.Max(img1.Height,
img2.Height));
Graphics g = Graphics.FromImage(bmp);
g.DrawImage(img1, 0, 0,img1.Width,img1.Height);
g.DrawImage(img2, img1.Width, 0,img2.Width,img2.Height);
Pen redPen = new Pen(Color.Red);
Pen bluePen = new Pen(Color.Blue);
Pen matchPen = new Pen(Color.Gold);
Pen myPen;
int x = 0;
for (int i = 0; i < matches.Length;i++ )
{
foreach (IPoint ip in matches[i])
{
int S = 2 * Convert.ToInt32(2.5f * ip.scale);
int R = Convert.ToInt32(S / 2f);
System.Drawing.Point pt = new System.Drawing.Point(Convert.ToInt32(ip.x),
Convert.ToInt32(ip.y));
System.Drawing.Point ptR = new System.Drawing.Point(Convert.ToInt32(R *
Math.Cos(ip.orientation)),
Convert.ToInt32(R * Math.Sin(ip.orientation)));
myPen = (ip.laplacian > 0 ? bluePen : redPen);
g.DrawEllipse(myPen, x+pt.X - R, pt.Y - R, S, S);
g.DrawLine(new Pen(Color.FromArgb(0, 255, 0)), new System.Drawing.Point(x +
pt.X, pt.Y), new System.Drawing.Point(x + pt.X + ptR.X, pt.Y + ptR.Y));
}
x += img1.Width;
}
for (int i = 0; i < matches[0].Count; i++)
{
System.Drawing.Point pt1 = new
System.Drawing.Point(Convert.ToInt32(matches[0][i].x), Convert.ToInt32(matches[0][i].y));
System.Drawing.Point pt2 = new System.Drawing.Point(img1.Width +
Convert.ToInt32(matches[1][i].x), Convert.ToInt32(matches[1][i].y));
g.DrawLine(matchPen, pt1, pt2);
}

Universitas Sumatera Utara

A-17

g.Dispose();
returnBitmap = bmp;
}

}
}
4. IntegralImage.cs
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Drawing;
namespace Gataulah
{
[Serializable]
public class IntegralImage
{
const float cR = .2989f;
const float cG = .5870f;
const float cB = .1140f;
internal float[,] matriks;
public int lebar, tinggi;
public float this[int y, int x]
{
get { return matriks[y, x]; }
set { matriks[y, x] = value; }
}
private IntegralImage(int lebar, int tinggi)
{
this.lebar = lebar;
this.tinggi = tinggi;
this.matriks = new float[tinggi, lebar];
}
//01
public static IntegralImage FromImage(BitPeta image)
{
IntegralImage pic = new IntegralImage(image.lebar, image.tinggi);

Universitas Sumatera Utara

A-18

float barissum = 0;
for (int x = 0; x < image.lebar; x++)
{
Color c = image.GetPixel(x, 0);
barissum += (cR * c.R + cG * c.G + cB * c.B) / 255f;
pic[0, x] = barissum;
}

for (int y = 1; y < image.tinggi; y++)
{
barissum = 0;
for (int x = 0; x < image.lebar; x++)
{
Color c = image.GetPixel(x, y);
barissum += (cR * c.R + cG * c.G + cB * c.B) / 255f;
pic[y, x] = barissum + pic[y - 1, x];
}
}
return pic;
}

public float BoxIntegral(int baris, int col, int bariss, int cols)
{
int r1 = Math.Min(baris, tinggi) - 1;
int c1 = Math.Min(col, lebar) - 1;
int r2 = Math.Min(baris + bariss, tinggi) - 1;
int c2 = Math.Min(col + cols, lebar) - 1;
float A = 0, B = 0, C = 0, D = 0;
if (r1 >= 0 && c1 >= 0) A = matriks[r1, c1];
if (r1 >= 0 && c2 >= 0) B = matriks[r1, c2];
if (r2 >= 0 && c1 >= 0) C = matriks[r2, c1];
if (r2 >= 0 && c2 >= 0) D = matriks[r2, c2];
return Math.Max(0, A - B - C + D);
}
public float HaarX(int baris, int kolom, int size)
{
return BoxIntegral(baris - size / 2, kolom, size, size / 2)
- 1 * BoxIntegral(baris - size / 2, kolom - size / 2, size, size / 2);

Universitas Sumatera Utara

A-19

}
public float HaarY(int baris, int kolom, int size)
{
return BoxIntegral(baris, kolom - size / 2, size / 2, size)
- 1 * BoxIntegral(baris - size / 2, kolom - size / 2, size / 2, size);
}
}
}
5. FastHessian.cs
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using MathNet.Numerics.LinearAlgebra;
namespace Gataulah
{
[Serializable]
public class FastHessian
{

private class simpananLayer
{
public int lebar, tinggi, langkah, saring;
public float[] simpanannya;
public byte[] laplasian;
public simpananLayer(int lebar, int tinggi, int langkah, int saring)
{
this.lebar = lebar;
this.tinggi = tinggi;
this.langkah = langkah;
this.saring = saring;
simpanannya = new float[lebar * tinggi];
laplasian = new byte[lebar * tinggi];
}
public byte getlaplasian(int baris, int kolom)
{
return laplasian[baris * lebar + kolom];
}
public byte getlaplasian(int baris, int kolom, simpananLayer src)

Universitas Sumatera Utara

A-20

{
int scale = this.lebar / src.lebar;
return laplasian[(scale * baris) * lebar + (scale * kolom)];
}
public float getsimpanan(int baris, int kolom)
{
return simpanannya[baris * lebar + kolom];
}
public float getsimpanan(int baris, int kolom, simpananLayer src)
{
int scale = this.lebar / src.lebar;
return simpanannya[(scale * baris) * lebar + (scale * kolom)];
}
}
public static List getIpoints(float thr, int oktaf, int init_contoh, IntegralImage img)
{
FastHessian fh = new FastHessian(thr, oktaf, init_contoh, img);
return fh.getIpoints();
}
public FastHessian(float thr, int oktaf, int init_contoh, IntegralImage img)
{
this.thr = thr;
this.oktaf = oktaf;
this.init_contoh = init_contoh;
this.img = img;
}
private float thr;
private int oktaf;
private int init_contoh;
private IntegralImage img;
private List ipts;
private List simpananPeta;
public List getIpoints()
{
int [,] saring_Peta = {{0,1,2,3}, {1,3,4,5}, {3,5,6,7}, {5,7,8,9}, {7,9,10,11}};
if (ipts == null) ipts = new List();
else ipts.Clear();
buildsimpananPeta();

Universitas Sumatera Utara

A-21

simpananLayer b, m, t;
for (int o = 0; o < oktaf; ++o) for (int i = 0; i = 1)
{
simpananPeta.Add(new simpananLayer(w, h, s, 9));
simpananPeta.Add(new simpananLayer(w, h, s, 15));
simpananPeta.Add(new simpananLayer(w, h, s, 21));
simpananPeta.Add(new simpananLayer(w, h, s, 27));
}
if (oktaf >= 2)
{
simpananPeta.Add(new simpananLayer(w / 2, h / 2, s * 2, 39));
simpananPeta.Add(new simpananLayer(w / 2, h / 2, s * 2, 51));
}

Universitas Sumatera Utara

A-22

if (oktaf >= 3)
{
simpananPeta.Add(new simpananLayer(w / 4, h / 4, s * 4, 75));
simpananPeta.Add(new simpananLayer(w / 4, h / 4, s * 4, 99));
}
if (oktaf >= 4)
{
simpananPeta.Add(new simpananLayer(w / 8, h / 8, s * 8, 147));
simpananPeta.Add(new simpananLayer(w / 8, h / 8, s * 8, 195));
}
if (oktaf >= 5)
{
simpananPeta.Add(new simpananLayer(w / 16, h / 16, s * 16, 291));
simpananPeta.Add(new simpananLayer(w / 16, h / 16, s * 16, 387));
}
for (int i = 0; i < simpananPeta.Count; ++i)
{
buildsimpananLayer(simpananPeta[i]);
}
}
private void buildsimpananLayer(simpananLayer rl)
{
int langkah = rl.langkah;
int b = (rl.saring - 1) / 2;
int l = rl.saring / 3;
int w = rl.saring;
float inverse_area = 1f / (w * w);
float Dxx, Dyy, Dxy;
for (int r, c, ar = 0, index = 0; ar < rl.tinggi; ++ar)
{
for (int ac = 0; ac < rl.lebar; ++ac, index++)
{
r = ar * langkah;
c = ac * langkah;
Dxx = img.BoxIntegral(r - l + 1, c - b, 2 * l - 1, w)
- img.BoxIntegral(r - l + 1, c - l / 2, 2 * l - 1, l) * 3;
Dyy = img.BoxIntegral(r - b, c - l + 1, w, 2 * l - 1)
- img.BoxIntegral(r - l / 2, c - l + 1, l, 2 * l - 1) * 3;
Dxy = + img.BoxIntegral(r - l, c + 1, l, l)
+ img.BoxIntegral(r + 1, c - l, l, l)
- img.BoxIntegral(r - l, c - l, l, l)
- img.BoxIntegral(r + 1, c + 1, l, l);

Universitas Sumatera Utara

A-23

Dxx *= inverse_area;
Dyy *= inverse_area;
Dxy *= inverse_area;
rl.simpanannya[index] = (Dxx * Dyy - 0.81f * Dxy * Dxy);
rl.laplasian[index] = (byte)(Dxx + Dyy >= 0 ? 1 : 0);
}
}
}
bool isExtremum(int r, int c, simpananLayer t, simpananLayer m, simpananLayer b)
{
int layerBorder = (t.saring + 1) / (2 * t.langkah);
if (r = t.tinggi - layerBorder || c = t.lebar layerBorder)
return false;
float candidate = m.getsimpanan(r, c, t);
if (candidate < thr)
return false;
for (int rr = -1; rr = candidate) ||
b.getsimpanan(r + rr, c + cc, t) >= candidate)
{
return false;
}
}
}
return true;
}
void interpolateExtremum(int r, int c, simpananLayer t, simpananLayer m, simpananLayer b)
{
matriks D = matriks.Create(BuildDerivative(r, c, t, m, b));
matriks H = matriks.Create(BuildHessian(r, c, t, m, b));
matriks Hi = H.Inverse();
matriks Of = -1 * Hi * D;
double[] O = { Of[0, 0], Of[1, 0], Of[2, 0] };

Universitas Sumatera Utara

A-24

int saringlangkah = (m.saring - b.saring);
if (Math.Abs(O[0]) < 0.5f && Math.Abs(O[1]) < 0.5f && Math.Abs(O[2]) < 0.5f)
{
IPoint ipt = new IPoint();
ipt.x = (float)((c + O[0]) * t.langkah);
ipt.y = (float)((r + O[1]) * t.langkah);
ipt.scale = (float)((0.1333f) * (m.saring + O[2] * saringlangkah));
ipt.laplasian = (int)(m.getlaplasian(r,c,t));
ipts.Add(ipt);
}
}
private double[,] BuildDerivative(int r, int c, simpananLayer t, simpananLayer m,
simpananLayer b)
{
double dx, dy, ds;
dx = (m.getsimpanan(r, c + 1, t) - m.getsimpanan(r, c - 1, t)) / 2f;
dy = (m.getsimpanan(r + 1, c, t) - m.getsimpanan(r - 1, c, t)) / 2f;
ds = (t.getsimpanan(r, c) - b.getsimpanan(r, c, t)) / 2f;
double[,] D = { { dx }, { dy }, { ds } };
return D;
}
private double[,] BuildHessian(int r, int c, simpananLayer t, simpananLayer m,
simpananLayer b)
{
double v, dxx, dyy, dss, dxy, dxs, dys;
v = m.getsimpanan(r, c, t);
dxx = m.getsimpanan(r, c + 1, t) + m.getsimpanan(r, c - 1, t) - 2 * v;
dyy = m.getsimpanan(r + 1, c, t) + m.getsimpanan(r - 1, c, t) - 2 * v;
dss = t.getsimpanan(r, c) + b.getsimpanan(r, c, t) - 2 * v;
dxy = (m.getsimpanan(r + 1, c + 1, t) - m.getsimpanan(r + 1, c - 1, t) m.getsimpanan(r - 1, c + 1, t) + m.getsimpanan(r - 1, c - 1, t)) / 4f;
dxs = (t.getsimpanan(r, c + 1) - t.getsimpanan(r, c - 1) b.getsimpanan(r, c + 1, t) + b.getsimpanan(r, c - 1, t)) / 4f;
dys = (t.getsimpanan(r + 1, c) - t.getsimpanan(r - 1, c) b.getsimpanan(r + 1, c, t) + b.getsimpanan(r - 1, c, t)) / 4f;
double[,] H = new double[3, 3];
H[0, 0] = dxx;
H[0, 1] = dxy;
H[0, 2] = dxs;
H[1, 0] = dxy;

Universitas Sumatera Utara

A-25

H[1, 1] = dyy;
H[1, 2] = dys;
H[2, 0] = dxs;
H[2, 1] = dys;
H[2, 2] = dss;
return H;
}

}
}
6. EuclideanDistance.cs
using System;
using System.Collections.Generic;
using System.Text;
namespace Gataulah
{
public class Utils
{
private const float FLT_MAX = 3.402823466e+38F;
public static List[] getMatches(List ipts1, List ipts2)
{
double dist;
double d1, d2;
IPoint match = new IPoint();
List[] matches = new List[2];
matches[0] = new List();
matches[1] = new List();
for (int i = 0; i < ipts1.Count; i++)
{
d1 = d2 = FLT_MAX;
for (int j = 0; j < ipts2.Count; j++)
{
dist = EuclideanDistance(ipts1[i], ipts2[j]);
if (dist < d1)
{
d2 = d1;
d1 = dist;
match = ipts2[j];

Universitas Sumatera Utara

A-26

}
else if (dist < d2)
{
d2 = dist;
}
}
if (d1 / d2 < 0.77)
{
matches[0].Add(ipts1[i]);
matches[1].Add(match);
}
}
return matches;
}

public static double EuclideanDistance(IPoint ip1, IPoint ip2)
{
int count = 0;
double sum = 0.0;

count = ip1.descriptor.Length;
for (int i = 0; i < count; i++)
{
sum += Math.Pow(Math.Abs(ip1.descriptor[i] - ip2.descriptor[i]), 2);
}
return Math.Sqrt(sum);
}
}
}

Universitas Sumatera Utara

B-1
CURRICULUM VITAE

Nama

: Aulia Tarindah Putri

Alamat Sekarang

: Jln. Gn. Leuser Blok A3 No.31 Tebing Tinggi

Alamat Orang Tua

: Jln. Gn. Leuser Blok A3 No.31 Tebing Tinggi

Telp/ Hp

: +6282366661549

Email

: auliatarindahputri@gmail.com

Riwayat Pendidikan
2012 – 2016

: S1 Ilmu Komputer Universitas Sumatera Utara, Medan

2009 – 2012

: SMA Negeri 1 Tebing Tinggi

2006 – 2009

: SMP Negeri 1 Tebing Tinggi

2000 – 2006

: SD R.A. Kartini Sei Rampah

Keahlian
Bahasa

: Indonesia, Inggris

Pemrograman

: C#, Java Android

Database

: MySql

Desain

: Photoshop, Corel Draw

Perkantoran

: Microsoft Office

Kursus yang diikuti
TOEFL, IELTS
Pengalaman Organisasi
[2006 – 2008]

Pramuka SMP Negeri 1

[2010 – 2012]

OSIS SMA Negeri 1

[2013 – 2016]

Pengajar IKLC 2013 - 2016

Universitas Sumatera Utara

B-2

[2013– 2015]

Imilkom USU

[2014– 2015]

PEMA Fasilkom-TI USU

Pengalaman Kepanitiaan
[2012]

Sekretaris Dies Natalis IMILKOM 2012

[2015]

Ketua Panitia Seminar Karir PT. Paragon - Wardah

Seminar
[2014]

Seminar Nasional Literasi Informasi “SENARAI”

Universitas Sumatera Utara

C-1

DAFTAR PENGGUNA

Universitas Sumatera Utara

C-2

DAFTAR PENGGUNA

Universitas Sumatera Utara

C-3

DAFTAR PENGGUNA

Universitas Sumatera Utara

C-4

DAFTAR PENGGUNA

Universitas Sumatera Utara

C-5

DAFTAR PENGGUNA

Universitas Sumatera Utara