diff --git a/README.md b/README.md index c1103dd..afb76b1 100644 --- a/README.md +++ b/README.md @@ -23,18 +23,20 @@ __Цель данной работы__ - реализовать набор пр __Основные задачи__ - 1. Разработать программную реализацию сглаживания посредством вычисления - среднего по окрестности. Границы обработать посредством зеркального - отображения пикселей (`gfedcb|abcdefgh|gfedcba`). 1. Реализовать линейный фильтр с произвольным ядром. Граница дополнена - нулевыми значениями. + нулевыми значениями. Ведущий элемент в центре ядра. 1. Разработать реализацию медианного фильтра. При вычислении использовать - только пиксели внутри изображения. - 1. Реализовать горизонтальный фильтр Собеля. Границы обработать посредством - зеркального отображения пикселей (`gfedcb|abcdefgh|gfedcba`). + только пиксели внутри изображения. Размер ядра - нечетная величина, ведущий + элемент ядра находится в центре ядра. __Дополнительные задачи__ - + 1. Разработать программную реализацию сглаживания посредством вычисления + среднего по окрестности. Границы обработать посредством зеркального + отображения пикселей (`gfedcb|abcdefgh|gfedcba`). Угловые пиксели + отображаются зеркально вдоль главной и побочной диагоналей. + 1. Реализовать горизонтальный фильтр Собеля. Границы обработать посредством + зеркального отображения пикселей (`gfedcb|abcdefgh|gfedcba`). Угловые + пиксели отображаются зеркально вдоль главной и побочной диагоналей. 1. Расширить реализацию класса матриц следующими операциями и тестами к ним: 1. Транспонирование матрицы. 1. Умножение матриц (в виде перегрузки операции). @@ -55,17 +57,23 @@ __Дополнительные задачи__ 1. Создать рабочую ветку для размещения реализаций фильтров (раздел [Общие инструкции по работе с Git][git-intro]). 1. Создать собственного наследника `FiltersSurname` от абстрактного класса фильтров. - 1. Реализовать последовательно все чисто виртуальные методы базового класса - - методы фильтрации, перечисленные в разделе [Основные задачи][tasks]. - 1. При реализации каждого фильтра следует пересобрать проект и проверить - работоспособность тестов. Изменения необходимо постоянно фиксировать, - выкладывая в рабочую ветку на сервер (раздел - [Общие инструкции по работе с Git][git-intro]). - 1. Сделать Pull Request в upstream-репозиторий. - 1. Выбрать и решить одну из задач списка [Дополнительные задачи][tasks]. - Необходимо проконтролировать, чтобы задача не была выбрана другими - участниками школы. В противном случае, в основной репозиторий попадет - первая полностью готовая реализация. + 1. Реализовать в наследнике последовательно чисто виртуальные методы + базового класса - методы фильтрации, перечисленные в разделе + [Основные задачи][tasks] (линейный и медианный фильтры). + 1. При реализации каждого фильтра следует пересобрать проект и проверить + работоспособность тестов. + Рекомендации: + - Отключить тесты для фильтров, которые не реализованы в вашем классе + до настоящего момента (вставьте `DISABLED_` перед названием теста). + - Изменения необходимо постоянно фиксировать, выкладывая + в рабочую ветку на сервер (раздел + [Общие инструкции по работе с Git][git-intro]). + 1. Сделать Pull Request в репозиторий upstream. + 1. Выбрать и решить одну из задач списка + [Дополнительные задачи][tasks]. + Начиная с третьей задачи, необходимо проконтролировать, чтобы задача + не была выбрана другими участниками школы. В противном случае, + в основной репозиторий попадет первая полностью готовая реализация. ## Общая структура проекта @@ -471,22 +479,19 @@ __Примечание:__ генератор проекта должен сов 1. Создать собственного наследника `FiltersYourName` от абстрактного класса фильтров. 1. Создать файл `filters_YOUR_NAME.cpp` (файл с реализацией в файловой системе) для собственных реализаций фильтров. - 1. В качестве шаблона необходимо воспользоваться `filters_opencv.cpp`. - Можно скопировать класс без реализации методов из файла - `filters_opencv.cpp` в файл `filters_YOUR_NAME.cpp`, заменив - название класса `FiltersOpenCV` на `FiltersYourName` (ниже приведен + 1. Добавьте в созданный файл класс `FiltersYourName` (ниже приведен фрагмент кода). ```cpp class FiltersYourName : public Filters { - public: - virtual void boxFilter(const Matrix &src, Matrix& dst, const int kSize = 3) - { } + public: virtual void filter2d(const Matrix &src, Matrix& dst, const Matrix &kernel) { } virtual void median(const Matrix &src, Matrix &dst, const int kSize = 3) { } + virtual void boxFilter(const Matrix &src, Matrix& dst, const int kSize = 3) + { } virtual void SobelOx(const Matrix &src, Matrix &dst) { } }; @@ -504,7 +509,7 @@ __Примечание:__ генератор проекта должен сов 1. В функции `Filters* createFilters(FILTERS_IMPLEMENTATIONS impl)` (файл `filters_factory.cpp`) необходимо добавить еще одну ветку у оператора- переключателя `switch`, по которой будет проходить исполнение программы, - если создан объект класса фильтров `YOUR_NAME`. + если создается объект класса фильтров `YOUR_NAME`. 1. В файл `filters_YOUR_NAME.cpp` необходимо поместить реализацию функции создания объекта класса фильтров с вашей реализацией `Filters* createFiltersYourName()`. Указание: для примера можно @@ -513,14 +518,14 @@ __Примечание:__ генератор проекта должен сов ```cpp Filters* createFiltersYourName() { - Filters* filters = new createFiltersYourName(); + Filters* filters = new FiltersYourName(); return filters; } ``` 1. После выполнения перечисленных действий проект должен успешно компилироваться, но тесты с вашей реализацией фильтров будут падать. - 1. Реализовать последовательно все чисто виртуальные методы базового класса - + 1. Реализовать последовательно чисто виртуальные методы базового класса - методы фильтрации, перечисленные в разделе [Основные задачи][tasks]. Обратите внимание, что у каждого фильтра свой способ обработки краевых пикселей на изображении. @@ -540,9 +545,9 @@ __Примечание:__ генератор проекта должен сов работоспособность тестов на Travis-CI и позволить преподавателям сделать ревью Вашего кода. 1. Выбрать и решить одну из задач списка [Дополнительные задачи][tasks]. - Необходимо проконтролировать, чтобы задача не была выбрана другими - участниками школы. В противном случае, в основной репозиторий попадет - первая полностью готовая реализация. + Начиная с третьей задачи, необходимо проконтролировать, чтобы задача + не была выбрана другими участниками школы. В противном случае, + в основной репозиторий попадет первая полностью готовая реализация. diff --git a/include/filters.hpp b/include/filters.hpp index c86c095..57eeadf 100644 --- a/include/filters.hpp +++ b/include/filters.hpp @@ -15,8 +15,7 @@ class Filters enum FILTERS_IMPLEMENTATIONS { OPENCV, - // Add your enum value here - // YOUR_NAME, + KUSTIKOVA, NUM_IMPLS }; diff --git a/src/filters_factory.cpp b/src/filters_factory.cpp index c977bf3..4d02b3d 100644 --- a/src/filters_factory.cpp +++ b/src/filters_factory.cpp @@ -1,17 +1,15 @@ #include "filters.hpp" Filters* createFiltersOpenCV(); -// Declare your implementation here -// Filters* createFiltersYourName(); +Filters* createFiltersKustikova(); Filters* createFilters(FILTERS_IMPLEMENTATIONS impl) { switch (impl) { case OPENCV: return createFiltersOpenCV(); - // Add case for your implementation - // case YOUR_NAME: - // return createFiltersYourName(); + case KUSTIKOVA: + return createFiltersKustikova(); default: return 0; } diff --git a/src/filters_kustikova.cpp b/src/filters_kustikova.cpp new file mode 100644 index 0000000..c1e3922 --- /dev/null +++ b/src/filters_kustikova.cpp @@ -0,0 +1,583 @@ +#include "filters.hpp" + +class FiltersKustikova : public Filters +{ + public: + virtual void boxFilter(const Matrix &src, Matrix& dst, const int kSize = 3) + { + + } + + virtual void filter2d(const Matrix &src, Matrix& dst, const Matrix &kernel) + { + if (kernel.rows() != kernel.cols()) + { + std::cout << "Kernel should have square sizes." << std::endl; + return; + } + filter2dInternalPoints(src, dst, kernel); + filter2dTopBorderPoints(src, dst, kernel); + filter2dButtomBorderPoints(src, dst, kernel); + filter2dLeftBorderPoints(src, dst, kernel); + filter2dRightBorderPoints(src, dst, kernel); + filter2dCornersPoints(src, dst, kernel); + } + + virtual void median(const Matrix &src, Matrix &dst, const int kSize = 3) + { + dst = src; + medianFilterInternalPoints(src, dst, kSize); + medianFilterTopPoints(src, dst, kSize); + medianFilterBottomPoints(src, dst, kSize); + medianFilterLeftBorderPoints(src, dst, kSize); + medianFilterRightBorderPoints(src, dst, kSize); + medianFilterCornersPoints(src, dst, kSize); + } + + virtual void SobelOx(const Matrix &src, Matrix &dst) + { + + } +private: + void sort(uchar *neigbors, int size) + { + for (int i = 0; i < size; i++) + { + for (int j = i + 1; j < size; j++) + { + if (neigbors[i] > neigbors[j]) + { + uchar tmp = neigbors[i]; + neigbors[i] = neigbors[j]; + neigbors[j] = tmp; + } + } + } + } + + void medianFilterInternalPoints(const Matrix &src, Matrix &dst, const int kSize) + { + int kSize2 = kSize / 2, idx = 0, + size = kSize * kSize, medIdx = size / 2; + uchar *neigbors = new uchar[size]; + for (int i = kSize2; i < src.rows() - kSize2; i++) + { + for (int j = kSize2; j < src.cols() - kSize2; j++) + { + idx = 0; + for (int k = -kSize2; k <= kSize2; k++) + { + for (int s = -kSize2; s <= kSize2; s++) + { + neigbors[idx++] = src[i + k][j + s]; + } + } + sort(neigbors, size); + dst[i][j] = neigbors[medIdx]; + } + } + delete []neigbors; + } + + void medianFilterTopPoints(const Matrix &src, Matrix &dst, const int kSize) + { + int kSize2 = kSize / 2, idx = 0, + size = kSize * kSize, medIdx = size / 2; + uchar *neigbors = new uchar[size]; + for (int j = kSize2; j < src.cols() - kSize2; j++) + { + idx = 0; + // 0 0 0 + // 1 1 1 + // 0 0 0 + for (int s = -kSize2; s <= kSize2; s++) + { + neigbors[idx++] = src[0][j + s]; + } + // 1 1 1 + // 0 0 0 + // 0 0 0 + for (int l = 0; l < kSize2; l++) + { + for (int s = -kSize2; s <= kSize2; s++) + { + neigbors[idx++] = src[0][j + s]; + } + } + // 0 0 0 + // 0 0 0 + // 1 1 1 + for (int k = 1; k <= kSize2; k++) + { + for (int s = -kSize2; s <= kSize2; s++) + { + neigbors[idx++] = src[k][j + s]; + } + } + sort(neigbors, size); + dst[0][j] = neigbors[medIdx]; + } + delete []neigbors; + } + + void medianFilterBottomPoints(const Matrix &src, Matrix &dst, const int kSize) + { + int kSize2 = kSize / 2, idx = 0, kRows = src.rows(), + size = kSize * kSize, medIdx = size / 2; + uchar *neigbors = new uchar[size]; + for (int j = kSize2; j < src.cols() - kSize2; j++) + { + idx = 0; + // 0 0 0 + // 1 1 1 + // 0 0 0 + for (int s = -kSize2; s <= kSize2; s++) + { + neigbors[idx++] = src[kRows - 1][j + s]; + } + // 1 1 1 + // 0 0 0 + // 0 0 0 + for (int l = 0; l < kSize2; l++) + { + for (int s = -kSize2; s <= kSize2; s++) + { + neigbors[idx++] = src[kRows - 1][j + s]; + } + } + // 0 0 0 + // 0 0 0 + // 1 1 1 + for (int k = -kSize2; k <= -1; k++) + { + for (int s = -kSize2; s <= kSize2; s++) + { + neigbors[idx++] = src[kRows + k - 1][j + s]; + } + } + sort(neigbors, size); + dst[kRows - 1][j] = neigbors[medIdx]; + } + delete []neigbors; + } + + void medianFilterLeftBorderPoints( + const Matrix &src, Matrix &dst, const int kSize) + { + int kSize2 = kSize / 2, idx = 0, kRows = src.rows(), + size = kSize * kSize, medIdx = size / 2; + uchar *neigbors = new uchar[size]; + for (int i = kSize2; i < src.rows() - kSize2; i++) + { + idx = 0; + // 0 1 0 + // 0 1 0 + // 0 1 0 + for (int k = -kSize2; k <= kSize2; k++) + { + neigbors[idx++] = src[i + k][0]; + } + // 1 0 0 + // 1 0 0 + // 1 0 0 + for (int l = 0; l < kSize2; l++) + { + for (int k = -kSize2; k <= kSize2; k++) + { + neigbors[idx++] = src[i + k][0]; + } + } + // 0 0 1 + // 0 0 1 + // 0 0 1 + for (int k = -kSize2; k <= kSize2; k++) + { + for (int s = 1; s <= kSize2; s++) + { + neigbors[idx++] = src[i + k][s]; + } + } + sort(neigbors, size); + dst[i][0] = neigbors[medIdx]; + } + delete []neigbors; + } + + void medianFilterRightBorderPoints( + const Matrix &src, Matrix &dst, const int kSize) + { + int kSize2 = kSize / 2, idx = 0, kCols = src.cols(), + size = kSize * kSize, medIdx = size / 2; + uchar *neigbors = new uchar[size]; + for (int i = kSize2; i < src.rows() - kSize2; i++) + { + idx = 0; + // 0 1 0 + // 0 1 0 + // 0 1 0 + for (int k = -kSize2; k <= kSize2; k++) + { + neigbors[idx++] = src[i + k][kCols - 1]; + } + // 1 0 0 + // 1 0 0 + // 1 0 0 + for (int l = 0; l < kSize2; l++) + { + for (int k = -kSize2; k <= kSize2; k++) + { + neigbors[idx++] = src[i + k][kCols - 1]; + } + } + // 0 0 1 + // 0 0 1 + // 0 0 1 + for (int k = -kSize2; k <= kSize2; k++) + { + for (int s = -kSize2; s <= -1; s++) + { + neigbors[idx++] = src[i + k][kCols + s - 1]; + } + } + sort(neigbors, size); + dst[i][kCols - 1] = neigbors[medIdx]; + } + delete []neigbors; + } + + void medianFilterCorner00( + const Matrix &src, Matrix &dst, const int kSize) + { + int kSize2 = kSize / 2, idx = 0, + size = kSize * kSize, medIdx = size / 2; + uchar *neigbors = new uchar[size]; + idx = 0; + // 0 0 0 + // 0 1 1 + // 0 1 1 + for (int k = 0; k <= kSize2; k++) + { + for (int s = 0; s <= kSize2; s++) + { + neigbors[idx++] = src[k][s]; + } + } + // 0 0 0 + // 1 0 0 + // 1 0 0 + for (int k = 0; k <= kSize2; k++) + { + neigbors[idx++] = src[k][0]; + } + // 0 1 1 + // 0 0 0 + // 0 0 0 + for (int s = 0; s <= kSize2; s++) + { + neigbors[idx++] = src[0][s]; + } + // 1 0 0 + // 0 0 0 + // 0 0 0 + for (int k = -kSize2; k <= -1; k++) + { + for (int s = -kSize2; s <= -1; s++) + { + neigbors[idx++] = src[0][0]; + } + } + sort(neigbors, size); + dst[0][0] = neigbors[medIdx]; + delete []neigbors; + } + + void medianFilterCorner01( + const Matrix &src, Matrix &dst, const int kSize) + { + int kSize2 = kSize / 2, idx = 0, kCols = src.cols(), + size = kSize * kSize, medIdx = size / 2; + uchar *neigbors = new uchar[size]; + idx = 0; + // 0 0 0 + // 1 1 0 + // 1 1 0 + for (int k = 0; k <= kSize2; k++) + { + for (int s = kCols - kSize2 - 1; s <= kCols - 1; s++) + { + neigbors[idx++] = src[k][s]; + } + } + // 0 0 0 + // 0 0 1 + // 0 0 1 + for (int k = 0; k <= kSize2; k++) + { + neigbors[idx++] = src[k][kCols - 1]; + } + // 1 1 0 + // 0 0 0 + // 0 0 0 + for (int s = kCols - kSize2 -1; s <= kCols - 1; s++) + { + neigbors[idx++] = src[0][s]; + } + // 0 0 1 + // 0 0 0 + // 0 0 0 + for (int k = 1; k <= kSize2; k++) + { + for (int s = 1; s <= kSize2; s++) + { + neigbors[idx++] = src[0][kCols - 1]; + } + } + sort(neigbors, size); + dst[0][kCols - 1] = neigbors[medIdx]; + delete []neigbors; + } + + void medianFilterCorner10( + const Matrix &src, Matrix &dst, const int kSize) + { + int kSize2 = kSize / 2, idx = 0, kRows = src.rows(), + size = kSize * kSize, medIdx = size / 2; + uchar *neigbors = new uchar[size]; + idx = 0; + // 0 1 1 + // 0 1 1 + // 0 0 0 + for (int k = kRows - kSize2 - 1; k <= kRows - 1; k++) + { + for (int s = 0; s <= kSize2; s++) + { + neigbors[idx++] = src[k][s]; + } + } + // 1 0 0 + // 1 0 0 + // 0 0 0 + for (int k = kRows - kSize2 - 1; k <= kRows - 1; k++) + { + neigbors[idx++] = src[k][0]; + } + // 0 0 0 + // 0 0 0 + // 0 1 1 + for (int s = 0; s <= kSize2; s++) + { + neigbors[idx++] = src[kRows - 1][s]; + } + // 0 0 0 + // 0 0 0 + // 1 0 0 + for (int k = 1; k <= kSize2; k++) + { + for (int s = -kSize2; s <= -1; s++) + { + neigbors[idx++] = src[kRows - 1][0]; + } + } + sort(neigbors, size); + dst[kRows - 1][0] = neigbors[medIdx]; + delete []neigbors; + } + + void medianFilterCorner11( + const Matrix &src, Matrix &dst, const int kSize) + { + int kSize2 = kSize / 2, idx = 0, kRows = src.rows(), + kCols = src.cols(), size = kSize * kSize, medIdx = size / 2; + uchar *neigbors = new uchar[size]; + idx = 0; + // 1 1 0 + // 1 1 0 + // 0 0 0 + for (int k = kRows - kSize2 - 1; k <= kRows - 1; k++) + { + for (int s = kCols - kSize2 - 1; s <= kCols - 1; s++) + { + neigbors[idx++] = src[k][s]; + } + } + // 0 0 1 + // 0 0 1 + // 0 0 0 + for (int k = kRows - kSize2 - 1; k <= kRows - 1; k++) + { + neigbors[idx++] = src[k][kCols - 1]; + } + // 0 0 0 + // 0 0 0 + // 1 1 0 + for (int s = kCols - kSize2 - 1; s <= kCols - 1; s++) + { + neigbors[idx++] = src[kRows - 1][s]; + } + // 0 0 0 + // 0 0 0 + // 0 0 1 + for (int k = 1; k <= kSize2; k++) + { + for (int s = 1; s <= kSize2; s++) + { + neigbors[idx++] = src[kRows - 1][kCols - 1]; + } + } + sort(neigbors, size); + dst[kRows - 1][kCols - 1] = neigbors[medIdx]; + delete []neigbors; + } + + void medianFilterCornersPoints( + const Matrix &src, Matrix &dst, const int kSize) + { + medianFilterCorner00(src, dst, kSize); + medianFilterCorner01(src, dst, kSize); + medianFilterCorner10(src, dst, kSize); + medianFilterCorner11(src, dst, kSize); + } + + void filter2dInternalPoints( + const Matrix &src, Matrix& dst, const Matrix &kernel) + { + int kSize = kernel.rows() / 2; + for (int i = kSize; i < src.rows() - kSize; i++) + { + for (int j = kSize; j < src.cols() - kSize; j++) + { + int conv = 0; + for (int k = -kSize; k <= kSize; k++) + { + for (int s = -kSize; s <= kSize; s++) + { + conv += kernel[k + kSize][s + kSize] * src[i + k][j + s]; + } + } + dst[i][j] = (conv > 255) ? 255 : (uchar)conv; + } + } + } + + void filter2dTopBorderPoints( + const Matrix &src, Matrix& dst, const Matrix &kernel) + { + int kSize = kernel.rows() / 2; + for (int j = kSize; j < src.cols() - kSize; j++) + { + int conv = 0; + for (int k = 0; k <= kSize; k++) + { + for (int s = -kSize; s <= kSize; s++) + { + conv += kernel[k + kSize][s + kSize] * src[k][j + s]; + } + } + dst[0][j] = (conv > 255) ? 255 : (uchar)conv; + } + } + + void filter2dButtomBorderPoints( + const Matrix &src, Matrix& dst, const Matrix &kernel) + { + int kSize = kernel.rows() / 2; + for (int j = kSize; j < src.cols() - kSize; j++) + { + int conv = 0; + for (int k = -kSize; k <= 0; k++) + { + for (int s = -kSize; s <= kSize; s++) + { + conv += kernel[k + kSize][s + kSize] * src[src.rows() - 1 + k][j + s]; + } + } + dst[src.rows() - 1][j] = (conv > 255) ? 255 : (uchar)conv; + } + } + + void filter2dLeftBorderPoints( + const Matrix &src, Matrix& dst, const Matrix &kernel) + { + int kSize = kernel.rows() / 2; + for (int i = kSize; i < src.rows() - kSize; i++) + { + int conv = 0; + for (int k = -kSize; k <= kSize; k++) + { + for (int s = 0; s <= kSize; s++) + { + conv += kernel[k + kSize][s + kSize] * src[i + k][s]; + } + } + dst[i][0] = (conv > 255) ? 255 : (uchar)conv; + } + } + + void filter2dRightBorderPoints( + const Matrix &src, Matrix& dst, const Matrix &kernel) + { + int kSize = kernel.rows() / 2; + for (int i = kSize; i < src.rows() - kSize; i++) + { + int conv = 0; + for (int k = -kSize; k <= kSize; k++) + { + for (int s = -kSize; s <= 0; s++) + { + conv += kernel[k + kSize][s + kSize] * src[i + k][src.cols() - 1 + s]; + } + } + dst[i][src.cols() - 1] = (conv > 255) ? 255 : (uchar)conv; + } + } + + void filter2dCornersPoints( + const Matrix &src, Matrix& dst, const Matrix &kernel) + { + int kSize = kernel.rows() / 2, conv = 0; + for (int k = 0; k <= kSize; k++) + { + for (int s = 0; s <= kSize; s++) + { + conv += kernel[k + kSize][s + kSize] * src[k][s]; + } + } + dst[0][0] = (conv > 255) ? 255 : (uchar)conv; + + conv = 0; + for (int k = 0; k <= kSize; k++) + { + for (int s = -kSize; s <= 0; s++) + { + conv += kernel[k + kSize][s + kSize] * src[k][src.cols() - 1 + s]; + } + } + dst[0][src.cols() - 1] = (conv > 255) ? 255 : (uchar)conv; + + conv = 0; + for (int k = -kSize; k <= 0; k++) + { + for (int s = 0; s <= kSize; s++) + { + conv += kernel[k + kSize][s + kSize] * src[src.rows() - 1 + k][s]; + } + } + dst[src.rows() - 1][0] = (conv > 255) ? 255 : (uchar)conv; + + conv = 0; + for (int k = -kSize; k <= 0; k++) + { + for (int s = -kSize; s <= 0; s++) + { + conv += kernel[k + kSize][s + kSize] * src[src.rows() - 1 + k][src.cols() - 1 + s]; + } + } + dst[src.rows() - 1][src.cols() - 1] = (conv > 255) ? 255 : (uchar)conv; + } +}; + +Filters* createFiltersKustikova() +{ + Filters* filters = new FiltersKustikova(); + return filters; +} diff --git a/test/filters_test.cpp b/test/filters_test.cpp index c63766e..457a0f9 100644 --- a/test/filters_test.cpp +++ b/test/filters_test.cpp @@ -25,7 +25,7 @@ class FiltersTest : public ::testing::TestWithParam Filters* filters; }; -TEST_P(FiltersTest, box_filter_on_zero_mat) +TEST_P(FiltersTest, DISABLED_box_filter_on_zero_mat) { Matrix src(5, 5), dst(5, 5), dstExp(5, 5); src.Zeros(); @@ -36,7 +36,7 @@ TEST_P(FiltersTest, box_filter_on_zero_mat) EXPECT_EQ(dstExp, dst); } -TEST_P(FiltersTest, box_filter_on_ones_mat) +TEST_P(FiltersTest, DISABLED_box_filter_on_ones_mat) { Matrix src(4, 4), dst(4, 4), expDst(4, 4); src.Ones(); @@ -47,7 +47,7 @@ TEST_P(FiltersTest, box_filter_on_ones_mat) EXPECT_EQ(expDst, dst); } -TEST_P(FiltersTest, box_filter_on_correct_mat) +TEST_P(FiltersTest, DISABLED_box_filter_on_correct_mat) { const std::string input = "./testdata/image.png"; const std::string expOutput = "./testdata/image_box_filter.png"; @@ -143,6 +143,43 @@ TEST_P(FiltersTest, median_on_zero_mat) EXPECT_EQ(dstExp, dst); } +TEST_P(FiltersTest, median_on_simple_mat) +{ + const int size = 4; + int elem = 0; + Matrix src(size, size), dst(size, size), dstExp(size, size); + for (int i = 0; i < size; i++) + { + for (int j = 0; j < size; j++) + { + src[i][j] = elem++; + } + } + dstExp[0][0] = 1; + dstExp[0][1] = 2; + dstExp[0][2] = 3; + dstExp[0][3] = 3; + + dstExp[1][0] = 4; + dstExp[1][1] = 5; + dstExp[1][2] = 6; + dstExp[1][3] = 7; + + dstExp[2][0] = 8; + dstExp[2][1] = 9; + dstExp[2][2] = 10; + dstExp[2][3] = 11; + + dstExp[3][0] = 12; + dstExp[3][1] = 12; + dstExp[3][2] = 13; + dstExp[3][3] = 14; + + filters->median(src, dst); + + EXPECT_EQ(dstExp, dst); +} + TEST_P(FiltersTest, median_on_correct_mat) { const std::string input = "./testdata/image.png"; @@ -172,7 +209,7 @@ TEST_P(FiltersTest, median_on_correct_mat) EXPECT_EQ(expDst, dst); } -TEST_P(FiltersTest, SobelOx_on_zero_mat) +TEST_P(FiltersTest, DISABLED_SobelOx_on_zero_mat) { Matrix src(5, 5), dst(5, 5), dstExp(5, 5); src.Zeros(); @@ -183,7 +220,7 @@ TEST_P(FiltersTest, SobelOx_on_zero_mat) EXPECT_EQ(dstExp, dst); } -TEST_P(FiltersTest, SobelOx_on_ones_mat) +TEST_P(FiltersTest, DISABLED_SobelOx_on_ones_mat) { Matrix src(4, 4), dst(4, 4), dstExp(4, 4); src.Ones(); @@ -194,7 +231,7 @@ TEST_P(FiltersTest, SobelOx_on_ones_mat) EXPECT_EQ(dstExp, dst); } -TEST_P(FiltersTest, sobel_ox_on_correct_mat) +TEST_P(FiltersTest, DISABLED_sobel_ox_on_correct_mat) { const std::string input = "./testdata/image.png"; const std::string expOutput = "./testdata/image_sobel_ox.png";