Правительство Российской Федерации
Федеральное государственное автономное образовательное учреждение высшего образовательного образования
“Национальный исследовательский университет
“Высшая школа экономики”
Московский институт электроники и математики Национального исследовательского университета «Высшая школа экономики»
Факультет информационных технологий и вычислительной техники
Кафедра Информационно-коммуникационных технологий
Курсовая работа
Тема
Размытие по Гауссу
Выполнил:
Студент группы ИКТ-21
Проверил:
______________________
______________________
«»2014 г.
Оценка:_______________
Москва, 2014
Аннотация
Программная реализация фильтра «Размытие по Гауссу» с последующими примерами на изображениях. Представлена блок-схема действия этого фильтра.
Оглавление
Что такое Размытие по Гауссу. 6
Задание
Программная реализация фильтра «Размытие по Гауссу». Написать и продемонстрировать работу фильтра. Программа должна уметь загружать изображения с диска и/или URL и сохранять результат. Все настройки должны быть в графическом интерфейсе программы.
План работы
- Что такое Размытие по Гауссу.
- Алгоритм работы
- Блок-схема программы
- Код программы
Ход работы
Что такое Размытие по Гауссу.
Размытие по Гауссу — это характерный фильтр размытия изображения, который использует нормальное распределение (также называемое Гауссовым распределением,
отсюда название) для вычисления преобразования, применяемого к каждому пикселю изображения.
Наиболее общая формула функция:
Рисунок 1. Функция Гаусса
Алгоритм работы фильтра
- Учитывая размер окна 2N+1, считаем точки опоры: xn= 3n/N, где n = -N, -N+1,…,N
- Рассчитываем значения G"n
- Рассчитываем коэффициент масштаба k'=∑G"n
- Рассчитываем размер окна G'n=G"n/k'
- Для каждого элемента:
А) Ищем его расположение относительно окна
Б) Берем все элементы
В) Умножаем элементы на соответствующийразмер окна
Г) Суммируем полученные результаты – это и есть отфильтрованное изображение
Блок-схема
Рисунок 2. Блок-схема функции "Размытие по Гауссу 1D"
Рисунок 3. Размытие по Гауссу 2D
Рисунок 4. Работа с памятью
Рисунок 5. Создание окна фильтра
Рисунок 6. Вставление данных
Рисунок 7. Создание фильтра
Код программы
gaussianblur.h
#ifndef _GAUSSIANBLUR_H_
#define _GAUSSIANBLUR_H_
template<class T = double> class TGaussianBlur
{
public:
// РазмытиепоГауссу 1D
bool Filter(T *pSignal, T *pResult, unsigned int N, unsigned int W) const;
// РазмытиепоГауссу 2D
bool Filter(T *pImage, T *pResult, unsigned int N, unsigned int M, unsigned int W) const;
protected:
// Структура массива данных
structCSize
{
unsignedint x; // Ширина
unsignedint y; // Высота
// Конструктор по умолчанию
CSize(): x(0), y(0) {}
// Конструктор с инициализацией
CSize(unsignedint _x, unsignedint _y): x(_x), y(_y) {}
// Инициализация
void Set(unsigned int _x, unsigned int _y) { x = _x; y = _y; }
// Область
unsignedint Area() const { return x * y; }
};
// Дескриптормассива
structCArray
{
CSize Size; // Размермассива
T *Buffer; // элемент памяти
// Конструктор по умолчанию
CArray(): Buffer(NULL) {}
// Конструктор с инициализацией
CArray(T *_Buffer, constCSize&_Size): Buffer(_Buffer), Size(_Size) {}
CArray(T *_Buffer, unsigned int _N): Buffer(_Buffer), Size(_N, 1) {}
};
// Дескриптормассивафильтра
structCExtension: public CArray
{
unsignedint Margin;
enumEMode {ModeHorizontal, ModeVertical};
// Конструкторпоумолчанию
CExtension(): Margin(0), Mode(ModeHorizontal) {}
// Деструктор
~CExtension() { if (Buffer) delete[] Buffer; }
// Установкарежимов
voidSetMode(EMode _Mode) { Mode = _Mode; }
bool Allocate(unsigned int _N, unsigned int _W) { return _Allocate(CSize(_N, 1), _W >> 1); }
bool Allocate(constCSize&_Size, unsigned int _W) { return _Allocate(_Size, _W >> 1); }
void Paste(const T * _Start);
void Extend();
protected:
EMode Mode;
bool _Allocate(constCSize&_Size, unsigned int _Margin);
};
// Окнофильтра
structCWindow
{
double *Weights; // Window weights
unsignedint Size; // Window size
// Конструкторпоумолчанию
CWindow(): Weights(NULL), Size(0), Correction(.5 - double(T(.5))) {}
// Деструктор
~CWindow() { if (Weights) delete[] Weights; }
// Созданиеокна
bool Create(unsigned int _Size);
// Окноприложения
T Apply(const T *_Element) const
{
// Нахождениепреобразования
double Sum = 0.;
const double *WeightIter = Weights;
const T *ElIter = _Element;
const double *const End = Weights + Size;
while (WeightIter< End)
Sum += *(WeightIter++) * double(*(ElIter++));
return T(Sum + Correction);
}
protected:
const double Correction;
};
// Проверкавходныхданных
bool Consistent(const T *_Image, constCSize&_Size, unsigned int _W) const { return _Image && _Size.x&& _Size.y&& _W && _Size.x> (_W >> 1) && _Size.y> (_W >> 1) && _W & 1; }
bool Consistent(const T *_Signal, unsigned int _N, unsigned int _W) const { return _Signal && _N && _W && _N > (_W >> 1) && _W & 1; }
};
#include "gaussianblur.cpp"
#endif
gaussianblur.cpp
#ifndef _GAUSSIANBLUR_CPP_
#define _GAUSSIANBLUR_CPP_
#include "gaussianblur.h"
#include <math.h>
// РазмытиепоГауссу 1D
template<class T>boolTGaussianBlur<T>::Filter(T *pSignal, T *pResult, unsigned int N, unsigned int W) const
{
// Проверкавходныхданных
if (!Consistent(pSignal, N, W))
return false;
CExtension Extension;
if (!Extension.Allocate(N, W))
return false;
// Созданиедескрипторасигнала
constCArray Signal(pSignal, N);
// Вставить сигнал в расширение
Extension.Paste(Signal.Buffer);
// Продление сигнала
Extension.Extend();
// Созданиеокнафильтра
CWindow Window;
if (!Window.Create(W))
return false;
const T *ExtIter = Extension.Buffer;
const T *constExtStop = Extension.Buffer + Extension.Size.x;
T *ResIter = pResult ?pResult :pSignal;
// Приминение фильтра к каждому элементу
while (ExtIter<ExtStop)
*(ResIter++) = Window.Apply(ExtIter++);
returntrue;
}
// Размытие по Гауссу 2D
template<class T>boolTGaussianBlur<T>::Filter(T *pImage, T *pResult, unsigned int N, unsigned int M, unsigned int W) const
{
// Проверкавходныхданных
if (!Consistent(pImage, CSize(N, M), W))
return false;
CExtension Extension;
if (!Extension.Allocate(CSize(N, M), W))
return false;
// Созданиедескриптораизображения
CArrayImage(pImage, CSize(N, M));
// Создание окна фильтра
CWindowWindow;
if (!Window.Create(W))
return false;
const T * ExtStop = Extension.Buffer + Extension.Size.x;
T *ResIter = pResult ?pResult :pImage;
const T *ImIter = Image.Buffer;
const T * ImStop = Image.Buffer + Image.Size.Area();
// Размываем по строкам
while (ImIter<ImStop)
{
// Берем изображение
Extension.Paste(ImIter);
// Разбиваем его по линиям
Extension.Extend();
const T *ExtIter = Extension.Buffer;
// Применяем фильтр к каждому пикселю на линии
while (ExtIter<ExtStop)
*(ResIter++) = Window.Apply(ExtIter++);
// Переходим к следующей линии
ImIter += Image.Size.x;
}
// Инициализируемизображение
Image.Buffer = pResult ?pResult :pImage;
// Устанавливаемвертикальныйрежим
Extension.SetMode(CExtension::ModeVertical);
ExtStop = Extension.Buffer + Extension.Size.y;
T *ResColumnIter = pResult ?pResult :pImage;
ImIter = Image.Buffer;
ImStop = Image.Buffer + Image.Size.x;
// Применяемфильтр к столбцам
while (ImIter<ImStop)
{
// Берем изображение
Extension.Paste(ImIter++);
// Разбиваем изображение по столбцам
Extension.Extend();
const T *ExtIter = Extension.Buffer;
ResIter = ResColumnIter;
// Применяем фильтр к каждому пикселю в столбце
while (ExtIter<ExtStop)
{
*ResIter = Window.Apply(ExtIter++);
ResIter += Image.Size.x;
}
// переходим к следующему столбцу
++ResColumnIter;
}
return true;
}
// Работа с памятью
template<class T>boolTGaussianBlur<T>::CExtension::_Allocate(constCSize&_Size, unsigned int _Margin)
{
// Выделяемпамять
Buffer = new T[(_Size.x> _Size.y ? _Size.x : _Size.y) + (_Margin << 1)];
// Проверямпамять
if (!Buffer)
return false;
Size = _Size;
Margin = _Margin;
return true;
}
template<class T> void TGaussianBlur<T>::CExtension::Paste(const T *const _Start)
{
if (Mode == ModeHorizontal)
{
memcpy(Buffer + Margin, _Start, Size.x * sizeof(T));
}
else
{
const T *const Stop = _Start + Size.Area();
const T *ArrIter = _Start;
T *ExtIter = Buffer + Margin;
// Берем массив столбцов элементов
while (ArrIter<Stop)
{
// Копируем линию
*(ExtIter++) = *ArrIter;
// Переходим к следующей линии
ArrIter += Size.x;
}
}
}
// Созданиефильтра
template<class T> void TGaussianBlur<T>::CExtension::Extend()
{
// Длиналинии
const unsigned int Line = Mode == ModeHorizontal ? Size.x :Size.y;
const T *const Stop = Buffer - 1;
T *ExtLeft = Buffer + Margin - 1;
const T *ArrLeft = ExtLeft + 2;
T *ExtRight = ExtLeft + Line + 1;
const T *ArrRight = ExtRight - 2;
// Берем массив линий элементов
while (ExtLeft>Stop)
{
*(ExtLeft--) = *(ArrLeft++);
*(ExtRight++) = *(ArrRight--);
}
}
// Созданиеокнафильтра
template<class T>boolTGaussianBlur<T>::CWindow::Create(unsigned int _Size)
{
// Выделяемпамять
Weights = new double[_Size];
// Проверка
if (!Weights)
return false;
// Устанавливаем размер окна
Size = _Size;
const unsigned int Half = Size >> 1;
Weights[Half] = 1.;
for (unsigned int Weight = 1; Weight < Half + 1; ++Weight)
{
// Точкиопоры
const double x = 3.* double(Weight) / double(Half);
Weights[Half - Weight] = Weights[Half + Weight] = exp(-x * x / 2.);
}
// Суммирование всех результатов
doublek = 0.;
for (unsigned int Weight = 0; Weight < Size; ++Weight)
k += Weights[Weight];
// Масштаб
for (unsigned int Weight = 0; Weight < Size; ++Weight)
Weights[Weight] /= k;
return true;
}
#endif
Результаты
Был программно реализован фильтр «Размытие по Гауссу» и составлены блок схемы по работе программы. Ниже представлены результаты работы программы.
Тесты
Рисунок 8. До применения фильтра
Рисунок 9. После применения фильтра
Источники
http://en.wikipedia.org/wiki/Gaussian_blur
http://habrahabr.ru/post/151157/
http://www.interface.ru/home.asp?artId=31747
http://stackoverflow.com/questions/19413386/gaussian-blur-mean-filter-convolution
http://docs.gimp.org/en/plug-in-gauss.html