Смекни!
smekni.com

Програма обробки зображень (стр. 3 из 3)


H16  H18 відрізняються від фільтрів H13  H15 тим, що до центрального елемента матриці додана 1, тобто при фільтрації вихідне зображення накладається на контур.

Для виділення контурів і перепадів яскравості можуть застосовуватися нелінійні фільтри. У нелінійних алгоритмах використовують нелінійні оператори дискретного диференціювання. У фільтрі Робертса використовується маска, що переміщається 2:

диференціювання виробляється за допомогою одного з виражень

У фільтрі Собела використовується вікно 33:

Центральному (i,j) -му пікселу замість f i,j привласнюється значення яскравості

або
, де

На мал. 8 показані результати застосування фільтра Собела.

2.4. Опис та обґрунтування вибору складу технічних та програмних засобів

Згідно з поставленою задачею оберемо технічні та програмні засоби реалізації програми. Програма написана на мові програмування високого рівня (С#). Дана програма розрахована на операційні системи Windows 2000, NT, XP з встановленою середою .NET 2.0 чи 3.0.


3. Опис інтерфейсу програми

Програма має зручний та доступний інтерфейс для роботи з користувачем. На рис. 1 показано вигляд вікна спілкування з користувачемдо початку роботи з програмою.

Рис.1. Зображення діалогового вікна програми.

За допомогою меню „Файл” користувач має можливість відкрити файл з зображенням. У першій частині робочого вікна ми маємо змогу бачити не фільтроване зображення. Також меню „Файл” надає можливість зберегти файл під вибраним чи іншим ім’ям.

Меню „Фильтровать” надає змогу відфільтрувати зображення. Він має наступні підменю

1. Лапласіан

2. Гаусовий

3. Smoothing

4. Довільне ядро

Після обрання будь-якого пункту меню на екран виводиться вікно з ядром

Рис 2. Вікно з ядром

При натисненні на кнопку „ОК” ми бачимо вікно, що виводиться під час обрахунків.

Рис.3 Вікно, що повідомляє про проходження обрахунків

Після виконання обрахунків ми бачимо на головному вікні у другій його частині фільтроване зображення, відповідно до обраної фільтрації.

Також, користувач має можливість власноруч заповнити матрицю з коефіцієнтами.

Далі наведені результати роботи програми з різними фільтрами:


4. Перевірка функціонування програми

Програма повністю відповідає наведеному вище алгоритму.


ВИСНОВКИ

Розробивши програмну модель обробки файлів зображень, я дійшов висновку, що найбільша складність у подібних задачах є розробка досить універсального алгоритму та оформлення результатів (введення та вивід).


ДЖЕРЕЛА, ЩО ВИКОРИСТАНІ ПРИ РОЗРОБЦІ

1. В.Б. Жушма, Ф. Колокольцев, Р.Коринь, Ю. Мевшин, Т. Мовчан,Л.Д. Писаренко, Ю. Путилов. Роздільне унітарне перетворення зображень, УЖ МТиТ 1999 № 2-3.

2. В,Б, Жушма, Ф. Колокольцев, Р,Корннь, Ю, Мевшнн, Т.В, Мовчан, Л.Д. Писаренко, Ю. Путилов. Сингулярне перетворення зображень, УЖ МТиТ 1999 №4.

3. http://msdn2.microsoft.com/ru-ru/default.aspx


ДОДАТОК1

ЛІСТИНГ ПРОГРАМИ

MainForm.cs

usingSystem;

using System.Collections.Generic;

using System.ComponentModel;

using System.Data;

using System.Drawing;

using System.Text;

using System.Windows.Forms;

namespace Kursach

{

public partial class MainForm : Form

{

private string filename = "";

WaitForm win = null;

public MainForm()

{

InitializeComponent();

}

private void ExitToolStripMenuItem_Click(object sender, EventArgs e)

{

this.Close();

}

private void OpenToolStripMenuItem_Click(object sender, EventArgs e)

{

if (openFileDialog.ShowDialog() == DialogResult.OK)

picture.Image = new Bitmap(filename = openFileDialog.FileName);

}

private void SaveAsToolStripMenuItem_Click(object sender, EventArgs e)

{

if (saveFileDialog.ShowDialog() == DialogResult.OK)

{

picture.Image.Save(filename = saveFileDialog.FileName);

}

}

private void SaveToolStripMenuItem_Click(object sender, EventArgs e)

{

picture.Image.Save(filename);

}

private void лапласианToolStripMenuItem_Click(object sender, EventArgs e)

{

Start<Laplacian>(false);

}

public void Start<T>(bool edit) where T : IKernel, new()

{

IKernel kernel = new T();

Bitmap bitmap = new Bitmap(picture.Image);

if (new KernelForm(false, kernel).ShowDialog() == DialogResult.OK)

{

win = new WaitForm(backgroundWorker);

win.Show(this);

backgroundWorker.RunWorkerAsync(new StartParam(bitmap, kernel));

}

}

private void smoothingToolStripMenuItem_Click(object sender, EventArgs e)

{

Start<Smoothing>(false);

}

private void гаусовыйToolStripMenuItem_Click(object sender, EventArgs e)

{

Start<Gaussian>(false);

}

private void CustomToolStripMenuItem_Click(object sender, EventArgs e)

{

Start<Unknown>(true);

}

private void backgroundWorker_DoWork(object sender, DoWorkEventArgs e)

{

StartParam s = (StartParam)e.Argument;

pictureF.Image = Filter.Filtering(s.b, s.k.Kernel , backgroundWorker);

}

private void backgroundWorker_ProgressChanged(object sender, ProgressChangedEventArgs e)

{

win.progressBar.Value = e.ProgressPercentage;

}

private void backgroundWorker_RunWorkerCompleted(object sender, RunWorkerCompletedEventArgs e)

{

win.Close();

}

}

class StartParam

{

public Bitmap b = null;

public IKernel k = null;

public StartParam(Bitmap b, IKernel k)

{

this.b = b;

this.k = k;

}

}

}

WaitForm.cs

using System;

using System.Collections.Generic;

using System.ComponentModel;

using System.Data;

using System.Drawing;

using System.Text;

using System.Windows.Forms;

namespace Kursach

{

public partial class WaitForm : Form

{

BackgroundWorker bw;

public WaitForm(BackgroundWorker bw)

{

InitializeComponent();

this.bw = bw;

}

private void button1_Click(object sender, EventArgs e)

{

this.Close();

}

private void WaitForm_FormClosing(object sender, FormClosingEventArgs e)

{

if (bw.IsBusy)

bw.CancelAsync();

}

}

}

KernelForm.cs

using System;

using System.Collections.Generic;

using System.ComponentModel;

using System.Data;

using System.Drawing;

using System.Text;

using System.Windows.Forms;

namespace Kursach

{

public partial class KernelForm : Form

{

private bool allowEdit = false;

public bool AllowEdit

{

get { return allowEdit; }

set

{

allowEdit = value;

kernelgrid.ReadOnly = !value;

}

}

public KernelForm(bool editable, IKernel kernel)

{

InitializeComponent();

for (int i = 0; i < kernel.Kernel.GetUpperBound(0) + 1; i++)

{

kernelgrid.Rows.Add();

for (int j = 0; j < kernel.Kernel.GetUpperBound(1) + 1; j++)

{

kernelgrid.Rows[i].Cells[j].Value = kernel.Kernel.GetValue(i, j);

}

}

this.Text = kernel.Text;

AllowEdit = editable;

}

private void butCancel_Click(object sender, EventArgs e)

{

this.Close();

}

private void butOK_Click(object sender, EventArgs e)

{

DialogResult = DialogResult.OK;

this.Close();

}

}

}

Filter.cs

using System;

using System.Collections.Generic;

using System.Text;

using System.Drawing;

using System.ComponentModel;

namespace Kursach

{

static class Filter

{

public static Bitmap Filtering(Bitmap img, int[,] kernel, BackgroundWorker bw)

{

int[,] Mk = (int[,])kernel.Clone();

int[] H = new int[kernel.Length];

int counter = 0;

for (int i = 0; i <= kernel.GetUpperBound(0); i++)

for (int j = 0; j <= kernel.GetUpperBound(1); j++)

H[counter++] = kernel[i, j];

Bitmap ret = new Bitmap(img);

int norma = Max(Sum(H), 1);

for (int i = 2; i < img.Width - 2; i++)

{

for (int j = 2; j < img.Height - 2; j++)

{

int[] V = new int[25];

for (int k = 0; k < V.Length; k++)

V[k] = img.GetPixel(i - 1 + k / 5 - 1, j - 1 + k % 5 - 1).ToArgb();

long mul = MulScalar(V, H);

double d =(double)1 / (double)norma;

double px = (d * mul);

ret.SetPixel(i, j, Color.FromArgb((int)px));

}

bw.ReportProgress(100 * i / img.Width);

if (bw.CancellationPending)

return ret;

}

return ret;

}

private static int Sum(int[] arr)

{

int res = 0;

foreach (int i in arr)

res += i;

return res;

}

private static int Max(int first, int second)

{

if (first > second)

return first;

else

return second;

}

private static long MulScalar(int[] first, int[] second)

{

long res = 0;

for (int i = 0; i < first.Length; i++)

res += (first[i] * second[i]);

return res;

}

}

}

Kernel.cs

using System;

using System.Collections.Generic;

using System.Text;

namespace Kursach

{

public interface IKernel

{

int[,] Kernel

{

get;

}

string Text

{

get;

}

}

}

Kernels.cs

using System;

using System.Collections.Generic;

using System.Text;

namespace Kursach

{

class Gradient : IKernel

{

#region IKernel Members

public int[,] Kernel

{

get

{

return new int[,]

{ { 0, -1, 0, 1, 0},

{-1, -2, 0, 2, 1},

{-1, -2, 0, 2, 1},

{-1, -2, 0, 2, 1},

{0, -1, 0, 1, 0} };

}

}

public string Text

{

get { return "Градиентный"; }

}

#endregion

}

class Laplacian : IKernel

{

#region IKernel Members

public int[,] Kernel

{

get

{

return new int[,]

{ { -1, -1, -1, -1, -1},

{-1, -1, -1, -1, -1},

{-1, -1, 24, -1, -1},

{-1, -1, -1, -1, -1},

{-1, -1, -1, -1, -1}}; ;

}

}

public string Text

{

get { return "Лапласиана"; }

}

#endregion

}

class Smoothing : IKernel

{

#region IKernel Members

public int[,] Kernel

{

get

{

return new int[,]

{ { 1, 1, 1, 1, 1},

{1, 1, 1, 1, 1},

{1, 1, 0, 1, 1},

{1, 1, 1, 1, 1},

{1, 1, 1, 1, 1}};

}

}

public string Text

{

get { return "Smoothing"; }

}

#endregion

}

class Gaussian : IKernel

{

#region IKernel Members

public int[,] Kernel

{

get

{

return new int[,]

{{ 1, 2, 4, 2, 1},

{2, 4, 8, 4, 2},

{4, 8, 16, 8, 16},

{2, 4, 8, 4, 2},

{1, 2, 4, 2, 1}};

}

}

public string Text

{

get { return "Гаусовый"; }

}

#endregion

}

class Unknown : IKernel

{

#region IKernel Members

public int[,] Kernel

{

get

{

return new int[,]

{ { 0, 0, 0, 0, 0},

{0, 0, 0, 0, 0},

{0, 0, 0, 0, 0},

{0, 0, 0, 0, 0},

{0, 0, 0, 0, 0}};

}

}

public string Text

{

get { return "Произвольный"; }

}

#endregion

}

}

Program.cs

using System;

using System.Collections.Generic;

using System.Windows.Forms;

namespace Kursach

{

static class Program

{

/// <summary>

/// The main entry point for the application.

/// </summary>

[STAThread]

static void Main()

{

Application.EnableVisualStyles();

Application.SetCompatibleTextRenderingDefault(false);

Application.Run(new MainForm());

}

}

}