Форум программистов, компьютерный форум, киберфорум
C# для начинающих
Войти
Регистрация
Восстановить пароль
Блоги Сообщество Поиск Заказать работу  
 
Рейтинг 4.73/40: Рейтинг темы: голосов - 40, средняя оценка - 4.73
1 / 1 / 0
Регистрация: 03.11.2018
Сообщений: 42

Рефакторинг кода медианного фильтра черно-белого изображения

19.11.2018, 19:00. Показов 7656. Ответов 12
Метки нет (Все метки)

Студворк — интернет-сервис помощи студентам
Всем привет привет.
Есть такой код. Выполнял задание. Нужно было сделать медианный фильтр черно белого 2д изображения.
Код работает, уж слишком много ветвлений. Хотелось бы использовать больше Линков. Но что-то как то не вышло. Что можно придумать, что бы код не выглядел таким уродским?
Заранее благодарю!
C#
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
using System;
using System.Linq;
 
        /* 
         * Для борьбы с пиксельным шумом,
         * обычно применяют медианный фильтр, в котором цвет каждого пикселя, 
         * заменяется на медиану всех цветов в некоторой окрестности пикселя.
         * 
         * Используйте окно размером 3х3 для не граничных пикселей,
         * Окно размером 2х2 для угловых и 3х2 или 2х3 для граничных.
         */
 
namespace Recognizer
{
    internal static class MedianFilterTask
    {
 
        // The input is a massive. We will sorting and return middle value of this massive 
 
        public static double MedianProcessing(double[] notProcessPixels) 
        {
            Array.Sort(notProcessPixels);
            double median;
            double tempValue1;
            double tempValue2;
            int index;
 
            if (notProcessPixels.Length % 2 == 1)
            {
                index = notProcessPixels.Length / 2 + 1;
                median = notProcessPixels[index];
            }
 
            else
            {
                // get arithmetic mean
 
                tempValue1 = notProcessPixels[notProcessPixels.Length / 2];
                tempValue2 = notProcessPixels[notProcessPixels.Length / 2 + 1];
                median = (tempValue1 + tempValue2) / 2;
            }
            return Math.Round(median, 7);
        }
 
        public static double[,] MedianFilter(double[,] original)
        {
            double[,] resultMedianPixel = new double[original.GetLength(0), original.GetLength(1)];
            
 
                
            int width = original.GetLength(0)-1; // index of high column
            int height = original.GetLength(1)-1; // index of high line
 
 
            for (int i=0; i<=width; i += 3)
                for(int j=0; j<=height; j += 3)
                {
                    #region
                    if (i == 0 && j==0)
                    {
                        double[] tempArray = new double[] { original[i, j], original[i + 1, j], original[i, j + 1], original[i + 1, j + 1] };
                        double medValue = MedianProcessing(tempArray); // call the processing method
 
                        for (int b = 0; b < 2; b++)
                            for (int v = 0; v < 2; v++)
                                resultMedianPixel[b, v] = medValue;
                        continue;
                    }
 
                    else if (i == 0 && j == height)
                    {
                        double[] tempArray = new double[] { original[i, j], original[i + 1, j], original[i, j - 1], original[i + 1, j - 1] };
                        double medValue = MedianProcessing(tempArray);
 
                        for (int b = i; b < 2; b++)
                            for (int v = j; v > j - 2; v--)
                                resultMedianPixel[b, v] = medValue;
                        continue;
                    }
 
                    else if (i == width && j == 0)
                    {
                        double[] tempArray = new double[] { original[i, j], original[i - 1, j], original[i, j + 1], original[i - 1, j + 1] };
                        double medValue = MedianProcessing(tempArray);
 
                        for (int b = i; b > i - 2; b--)
                            for (int v = j; v < 2; v++)
                                resultMedianPixel[b, v] = medValue;
                        continue;
                    }
 
                    else if (i == width && j == height)
                    {
                        double[] tempArray = new double[] { original[i, j], original[i - 1, j], original[i, j - 1], original[i - 1, j - 1] };
                        double medValue = MedianProcessing(tempArray);
 
                        for (int b = i; b > i - 2; b--)
                            for (int v = j; v > j - 2; v--)
                                resultMedianPixel[b, v] = medValue;
                        continue;
                    }
 
 
                    else if (i == 0)
                    {
                        double[] tempArray = new double[] { original[i, j], original[i, j-1], original[i, j+1], original[i+1, j], original[i + 1, j-1], original[i + 1, j + 1] };
                        double medValue = MedianProcessing(tempArray);
 
                        for (int b = i; b <= i+1; b++)
                            for (int v = j-1; v <= j + 1; v++)
                                resultMedianPixel[b, v] = medValue;
                        continue;
                    }
 
                    else if (j == 0) 
                    {
                        double[] tempArray = new double[] { original[i - 1, j], original[i, j], original[i + 1, j], original[i -1, j + 1], original[i, j + 1], original[i + 1, j + 1] };
                        double medValue = MedianProcessing(tempArray);
 
                        for (int b = i-1; b <=i+1; b++)
                            for (int v = j; v >= j + 1; v++)
                                resultMedianPixel[b, v] = medValue;
                        continue;
                    }
 
                    else if (i == width) 
                    {
                        double[] tempArray = new double[] { original[i, j], original[i, j - 1], original[i, j + 1], original[i - 1, j], original[i - 1, j - 1], original[i - 1, j + 1] };
                        double medValue = MedianProcessing(tempArray);
 
                        for (int b = i; b >= i - 1; b--)
                            for (int v = j - 1; v <= j + 1; v++)
                                resultMedianPixel[b, v] = medValue;
                        continue;
                    }
 
                    else if (j == height) 
                    {
                        double[] tempArray = new double[] { original[i, j], original[i-1, j], original[i+1, j], original[i-1, j-1], original[i, j - 1], original[i + 1, j - 1] };
                        double medValue = MedianProcessing(tempArray);
 
                        for (int b = i - 1; b <= i + 1; b++)
                            for (int v = j; v >= j - 1; v--)
                                resultMedianPixel[b, v] = medValue;
                        continue;
                    }
 
                    else
                    {
                        double[,] cloneArray = (double[,])original.Clone();
                        double[] tempArray = new double[9];
                        int ind = 0;
                        for (int f = i-1; f <= i+1; f++)
                            for (int g = j-1; g <= j+1; g++)
                                tempArray[ind++] = cloneArray[f, g];
                        double medValue = MedianProcessing(tempArray);
 
                        for (int b = i - 1; b <= i + 1; b++)
                            for (int v = j-1; v <= j + 1; v++)
                                resultMedianPixel[b, v] = medValue;
                        continue;
                    }
                    #endregion
                }
 
            return resultMedianPixel;
        }
    }
}
0
Лучшие ответы (1)
cpp_developer
Эксперт
20123 / 5690 / 1417
Регистрация: 09.04.2010
Сообщений: 22,546
Блог
19.11.2018, 19:00
Ответы с готовыми решениями:

Обработка изображения с использованием медианного фильтра
Приветствую. Не сочтите за наглость, но может кто нибудь даст рабочий код обработки изображения с использованием медианного фильтра. ...

Получение чёрно-белого изображения
Помогите пожалуйста!!!! Как получить черно-белое изображение. 30% красного 59 зеленого и 11 % синего.

Skeletonize чёрно-белого изображения
Доброго времени суток! Стоит задача провести скелетирование ч/б изображения при помощи библиотек scikit-image и opencv. Проблема в том, что...

12
Модератор
Эксперт .NET
 Аватар для Элд Хасп
16124 / 11248 / 2888
Регистрация: 21.04.2018
Сообщений: 33,082
Записей в блоге: 2
19.11.2018, 19:12
Цитата Сообщение от privetprivet Посмотреть сообщение
Код работает, уж слишком много ветвлений. Хотелось бы использовать больше Линков.
LINQ - работает только со списками. Может работать с одномерным массивом так как он подобен списку.
У Вас источник original - плоская матрица. С таким источником LINQ, в принципе, не может работать. Нужно его преобразовывать в в список или список списков.
Кроме того, на сколько знаю, LINQ - может смотрица красивее и проще, но по скорости он не превосходит обычные циклы.
1
1 / 1 / 0
Регистрация: 03.11.2018
Сообщений: 42
19.11.2018, 19:21  [ТС]
Цитата Сообщение от Элд Хасп Посмотреть сообщение
LINQ - работает только со списками. Может работать с одномерным массивом так как он подобен списку.
У Вас источник original - плоская матрица. С таким источником LINQ, в принципе, не может работать. Нужно его преобразовывать в в список или список списков.
Кроме того, на сколько знаю, LINQ - может смотрица красивее и проще, но по скорости он не превосходит обычные циклы
хорошо. а как можно преобразовать этот код? не слишком ли много ветвлений...
0
Модератор
Эксперт .NET
 Аватар для Элд Хасп
16124 / 11248 / 2888
Регистрация: 21.04.2018
Сообщений: 33,082
Записей в блоге: 2
19.11.2018, 20:29
Цитата Сообщение от privetprivet Посмотреть сообщение
хорошо. а как можно преобразовать этот код? не слишком ли много ветвлений...
Надо вникать в алгоритм.
Сначала давайте рассмотрим основную ветку
C#
150
151
152
153
154
155
156
157
158
159
160
161
162
                        double[,] cloneArray = (double[,])original.Clone();
                        double[] tempArray = new double[9];
                        int ind = 0;
                        for (int f = i-1; f <= i+1; f++)
                            for (int g = j-1; g <= j+1; g++)
                                tempArray[ind++] = cloneArray[f, g];
                        double medValue = MedianProcessing(tempArray);
 
                        for (int b = i - 1; b <= i + 1; b++)
                            for (int v = j-1; v <= j + 1; v++)
                                resultMedianPixel[b, v] = medValue;
                        continue;
                    }
Что делает эта ветка?
0
1 / 1 / 0
Регистрация: 03.11.2018
Сообщений: 42
19.11.2018, 20:42  [ТС]
Цитата Сообщение от Элд Хасп Посмотреть сообщение
Надо вникать в алгоритм.
Сначала давайте рассмотрим основную ветку
когда главный пиксиль вокруг которого и захватывается область 3х3 находится не с краю. Предположим в центре. все пиксили 3х3 с этим пикселем в центре перезаписывают свои значения на medValue;
0
Модератор
Эксперт .NET
 Аватар для Элд Хасп
16124 / 11248 / 2888
Регистрация: 21.04.2018
Сообщений: 33,082
Записей в блоге: 2
19.11.2018, 20:54
Цитата Сообщение от privetprivet Посмотреть сообщение
когда главный пиксиль вокруг которого и захватывается область 3х3 находится не с краю. Предположим в центре. все пиксили 3х3 с этим пикселем в центре перезаписывают свои значения на medValue;
MedianProcessing(tempArray);Эта функция вычисляет нужное значение для матрицы 3х3. Портом вся эта матрица записывается этим значением. Так?

А на границах что происходит?
0
1 / 1 / 0
Регистрация: 03.11.2018
Сообщений: 42
19.11.2018, 21:14  [ТС]
Цитата Сообщение от Элд Хасп Посмотреть сообщение
MedianProcessing(tempArray);Эта функция вычисляет нужное значение для матрицы 3х3. Портом вся эта матрица записывается этим значением. Так?
А на границах что происходит?
MedianProcessing работает при любых значениях (ну разве что наше изображение равно 1 пикселю) ) просто вычесляет медианное значение элементов входящего массива.
Потом значение записывается в переменную и всем значениям вощедшего в MedianProcessing массива присваивается новое значение - medValue;

далее цикл фор идет дальше до конца. На границах матрицы в функцию MedianProcessing просто передается не 9 а 6 или 4 значения в зависимости от текущего местоположения.
0
Модератор
Эксперт .NET
 Аватар для Элд Хасп
16124 / 11248 / 2888
Регистрация: 21.04.2018
Сообщений: 33,082
Записей в блоге: 2
19.11.2018, 21:21
Лучший ответ Сообщение было отмечено privetprivet как решение

Решение

Допустим, если считать так:
C#
150
151
152
153
154
155
156
157
158
159
160
161
162
163
                        double[,] cloneArray = (double[,])original.Clone();
                        List<double> tempArray = new List<double>();
                        for (int f = i-1; f <= i+1; f++)
                            for (int g = j-1; g <= j+1; g++)
                                if (f >=0 && f<=width && g >= 0 && g <= height)
                                    tempArray.Add(cloneArray[f, g]);
                        double medValue = MedianProcessing(tempArray);
 
                        for (int b = i - 1; b <= i + 1; b++)
                            for (int v = j-1; v <= j + 1; v++)
                                if (b >=0 && b<=width && v >= 0 && v <= height)
                                    resultMedianPixel[b, v] = medValue;
                        continue;
                    }
Это не заменит все ветки?

Добавлено через 1 минуту
Не понял только первую строчку double[,] cloneArray = (double[,])original.Clone();
0
1 / 1 / 0
Регистрация: 03.11.2018
Сообщений: 42
19.11.2018, 21:33  [ТС]
Цитата Сообщение от Элд Хасп Посмотреть сообщение
Не понял только первую строчку double[,] cloneArray = (double[,])original.Clone();
это делаю глубокое копирование что вы не изменять значения входящего массива.

А на счет вашего кода сейчас подумаю. 5 сек...
0
Модератор
Эксперт .NET
 Аватар для Элд Хасп
16124 / 11248 / 2888
Регистрация: 21.04.2018
Сообщений: 33,082
Записей в блоге: 2
19.11.2018, 21:38
Цитата Сообщение от privetprivet Посмотреть сообщение
это делаю глубокое копирование что вы не изменять значения входящего массива.
Это я и так понимаю. Вопрос не об этом.
Для чего Вы это делаете? Может я что-то пропустил, но элементы original и cloneArray ни где не меняются. Так зачем было тогда клонировать массив?
0
1 / 1 / 0
Регистрация: 03.11.2018
Сообщений: 42
19.11.2018, 21:45  [ТС]
Цитата Сообщение от Элд Хасп Посмотреть сообщение
Это не заменит все ветки?
Ничего себе. Заменило. Спасибо большое. Там правда массив передается - MedianProcessing(tempArray.ToArray());

Все работает отлично!

Добавлено через 3 минуты
Цитата Сообщение от Элд Хасп Посмотреть сообщение
Это я и так понимаю. Вопрос не об этом.
Для чего Вы это делаете? Может я что-то пропустил, но элементы original и cloneArray ни где не меняются. Так зачем было тогда клонировать массив?
Это ошибка. Когда писал было много мыслей. Запутался в них. Но благодаря Вам разобрался. Спасибо
0
Модератор
Эксперт .NET
 Аватар для Элд Хасп
16124 / 11248 / 2888
Регистрация: 21.04.2018
Сообщений: 33,082
Записей в блоге: 2
19.11.2018, 21:45
Цитата Сообщение от privetprivet Посмотреть сообщение
Там правда массив передается - MedianProcessing(tempArray.ToArray());
Чем так - лучше переделайте тип параметра или добавьте перегрузку. List - это тоже массив и его можно использовать с индексатором.
А то .ToArray() некрасиво выглядит, да, и лишнее создание мусора - при больших значениях будет замедлять работу.
1
0 / 0 / 0
Регистрация: 01.08.2021
Сообщений: 3
01.08.2021, 12:11
C#
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
using System;
using System.Collections.Generic;
using System.Linq;
 
namespace Recognizer
{
    internal static class MedianFilterTask
    {
        public static double[,] MedianFilter(double[,] original)
        {
            var xDimension = original.GetLength(0);
            var yDimension = original.GetLength(1);
            var result = new double[xDimension, yDimension];
            var coordinateMatrix = new List<List<int>>();
            var medianMatrix = new List<double>();
 
            for (int x = 0; x < xDimension; x++)
                for (int y = 0; y < yDimension; y++)
                {
                    coordinateMatrix = CoordinateCount(x,y,xDimension,yDimension);
                    medianMatrix = MatrixCount(coordinateMatrix, original);
                    result[x, y] = MedianCount(medianMatrix.ToArray());
                }
 
            return result;
        }
 
        private static List<List<int>> CoordinateCount(int x, int y, int xDimension, int yDimension)
        {
            var result = new List<List<int>>();
            var xZero = x - 1;
            var yZero = y - 1;
            for (int i = xZero; i < xZero + 3; i++)
                for (int j = yZero; j <yZero+ 3; j++)
                    if (i >= 0 && i < xDimension && j >= 0 && j < yDimension)
                        result.Add(new List<int>() { i, j });
            return result;
        }
 
        private static List<double> MatrixCount(List<List<int>> coordinateMatrix, double[,] original)
        {
            var result = new List<double>();
            foreach (var item in coordinateMatrix)
                result.Add(original[item[0], item[1]]);
            return result;
        }
 
        public static double MedianCount(double[] matrix)
        {
            Array.Sort(matrix);
            var middleMatrix = matrix.Length / 2;
            if (matrix.Length % 2 == 0)
                return (matrix[middleMatrix - 1] + matrix[middleMatrix]) / 2;
            middleMatrix = (int)Math.Floor((double)middleMatrix);
            return matrix[middleMatrix]; ;
        }
    }
}
0
Надоела реклама? Зарегистрируйтесь и она исчезнет полностью.
raxper
Эксперт
30234 / 6612 / 1498
Регистрация: 28.12.2010
Сообщений: 21,154
Блог
01.08.2021, 12:11
Помогаю со студенческими работами здесь

Изменение цвета черно-белого изображения
Изменение цвета черно-белого изображения, чтоб получить цветная картинка

Запись чёрно-белого изображения bmp в двумерный массив и его сжатие/разжатие по Хаффману
Помогите, у меня задание: есть картинка (чёрно-белое изображение бмп) её необходимо записать в двумерный массив где b-чёрный пиксель...

Реализация медианного фильтра с применением sse2
Не знаю, на сколько это для начинающих. Но я только начинаю вникать в суть параллелизации. Суть в том, чтобы реализовать данный фильтр...

Реализация алгоритма реализации медианного фильтра с использованием LINQ
Вот задание с ресурса ulearn: &quot;Практика «Медианный фильтр» Продолжайте в том же проекте Перед преобразованием в черно-белое, с...

Обработка черно-белого рисунка
В Маткаде создана большая матрица 200 х 100 элементов - отсканированный черно-белый рисунок из черных пятен на белом фоне. Матрица...


Искать еще темы с ответами

Или воспользуйтесь поиском по форуму:
13
Ответ Создать тему
Новые блоги и статьи
SDL3 для Web (WebAssembly): Основы отладки веб-приложений на SDL3 по USB и Wi-Fi, запущенных в браузере мобильных устройств
8Observer8 07.02.2026
Содержание блога Браузер Chrome имеет средства для отладки мобильных веб-приложений по USB. В этой пошаговой инструкции ограничимся работой с консолью. Вывод в консоль - это часть процесса. . .
SDL3 для Web (WebAssembly): Обработчик клика мыши в браузере ПК и касания экрана в браузере на мобильном устройстве
8Observer8 02.02.2026
Содержание блога Для начала пошагово создадим рабочий пример для подготовки к экспериментам в браузере ПК и в браузере мобильного устройства. Потом напишем обработчик клика мыши и обработчик. . .
Философия технологии
iceja 01.02.2026
На мой взгляд у человека в технических проектах остается роль генерального директора. Все остальное нейронки делают уже лучше человека. Они не могут нести предпринимательские риски, не могут. . .
SDL3 для Web (WebAssembly): Вывод текста со шрифтом TTF с помощью SDL3_ttf
8Observer8 01.02.2026
Содержание блога В этой пошаговой инструкции создадим с нуля веб-приложение, которое выводит текст в окне браузера. Запустим на Android на локальном сервере. Загрузим Release на бесплатный. . .
SDL3 для Web (WebAssembly): Сборка C/C++ проекта из консоли
8Observer8 30.01.2026
Содержание блога Если вы откроете примеры для начинающих на официальном репозитории SDL3 в папке: examples, то вы увидите, что все примеры используют следующие четыре обязательные функции, а. . .
SDL3 для Web (WebAssembly): Установка Emscripten SDK (emsdk) и CMake для сборки C и C++ приложений в Wasm
8Observer8 30.01.2026
Содержание блога Для того чтобы скачать Emscripten SDK (emsdk) необходимо сначало скачать и уставить Git: Install for Windows. Следуйте стандартной процедуре установки Git через установщик. . . .
SDL3 для Android: Подключение Box2D v3, физика и отрисовка коллайдеров
8Observer8 29.01.2026
Содержание блога Box2D - это библиотека для 2D физики для анимаций и игр. С её помощью можно определять были ли коллизии между конкретными объектами. Версия v3 была полностью переписана на Си, в. . .
Инструменты COM: Сохранение данный из VARIANT в файл и загрузка из файла в VARIANT
bedvit 28.01.2026
Сохранение базовых типов COM и массивов (одномерных или двухмерных) любой вложенности (деревья) в файл, с возможностью выбора алгоритмов сжатия и шифрования. Часть библиотеки BedvitCOM Использованы. . .
КиберФорум - форум программистов, компьютерный форум, программирование
Powered by vBulletin
Copyright ©2000 - 2026, CyberForum.ru