Модераторы: Partizan, gambit
  

Поиск:

Ответ в темуСоздание новой темы Создание опроса
> Сглаживающий фильтр, вопрос реализации 
V
    Опции темы
emike
Дата 3.6.2008, 19:33 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Новичок



Профиль
Группа: Участник
Сообщений: 7
Регистрация: 30.5.2008

Репутация: нет
Всего: нет



Здравствуйте,

пытаюсь реализовать простой сглаживающий фильтр в Win Forms Application

Побродив по форуму, пришел к такому коду:

Исходные данные

Код

    // Размер массива
    const Byte rang = 250;
    // Маска фильтра 3х3
    const int mask3[3][3] = {{1,1,1},{1,1,1},{1,1,1}};

    // RGB массивы изображения
    Byte red_buf[rang][rang];
    Byte green_buf[rang][rang];
    Byte blue_buf[rang][rang];    

                    ...

    Bitmap^ bmp;
    Graphics^ g;
    Pen^ P;



1) Вывод картинки на экран:

Код

            Graphics^ g = e->Graphics;
            bmp = gcnew Bitmap("circles.bmp");
            int H = bmp->Height, W = bmp->Width;
            // Вывод изображения на экран
            e->Graphics->DrawImage(bmp,60,40,W,H);


2) Запись в три массива R,G,B:

Код

                Color pixelcolor;
                // Сохранение изображения в массивы RGB
                for (int i=0; i<W; i++)
                 for (int j=0; j<H; j++)
                 {
                     pixelcolor = bmp->GetPixel(i,j);
                     red_buf[i][j] = Byte(pixelcolor.R);
                     green_buf[i][j] = Byte(pixelcolor.G);
                     blue_buf[i][j] = Byte(pixelcolor.B);
                 }


3) Собственно обработка и вывод обработанного изображения на экран:

Код

                // Сглаживающий фильтр 3x3
                Byte Red = 0, Green = 0, Blue = 0;
                for (int i=2; i<W-1; i++)
                 for (int j=2; j<H-1; j++)
                 {
                    Red = 0, Green = 0, Blue = 0;
                    for (int x=-1; x<=1; x++)
                     for (int y=-1; y<=1; y++)
                     {
                        Red=Red+red_buf[i+x][j+y]*mask3[x+2][y+2]; // Все значения массива mask3 равны 1, размерность 3х3
                        Green=Green+green_buf[i+x][j+y]*mask3[x+2][y+2];
                        Blue=Blue+blue_buf[i+x][j+y]*mask3[x+2][y+2];
                     }
                    red_buf[i][j] = System::Math::Abs(Red/9);
                    green_buf[i][j] = System::Math::Abs(Green/9);
                    blue_buf[i][j] = System::Math::Abs(Blue/9);
                 }

                // Вывод изображения на экран
                for (int i=0; i<W; i++)
                    for (int j=0; j<H; j++)
                    {
                        P = gcnew Pen(System::Drawing::Color::FromArgb(red_buf[i][j],green_buf[i][j],blue_buf[i][j]));
                        e->Graphics->DrawLine(P,i+60,j+40,i+60,j+41);
                    }


В результате получаю черный квадрат. Что не так?

Буду благодарен любым замечаниям и советам smile 

P.S. Можно ли получить значения яркостей пикселей в диапазоне 0..255?


В прикрепленном файле - исходное изображение

Это сообщение отредактировал(а) emike - 3.6.2008, 19:37

Присоединённый файл ( Кол-во скачиваний: 7 )
Присоединённый файл  Circles.rar 37,07 Kb
PM MAIL   Вверх
marcusmae
Дата 3.6.2008, 22:01 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


stravaganza
**


Профиль
Группа: Участник
Сообщений: 874
Регистрация: 26.3.2006

Репутация: 22
Всего: 39



Цитата(emike @  3.6.2008,  19:33 Найти цитируемый пост)
В результате получаю черный квадрат. Что не так?


emike, я тоже вначале получил чёрный экран. Причина в девятках. После замены на двойку, что-то получилось, но не уверен, что это - то, что нужно smile 

Код

using System;
using System.Drawing;

namespace ImageFilter33
{
    class Program
    {
        static void Main(string[] args)
        {
            string inFilename = "input.jpg", outFilename = "output.jpg";
            const double scale = 2;
            byte[,] mask3 = new byte[,] { { 1, 1, 1 }, { 1, 1, 1 }, { 1, 1, 1 } };

            Program.Filter33(new Bitmap(inFilename), mask3, scale).Save(
                outFilename, System.Drawing.Imaging.ImageFormat.Jpeg);
        }

        static Bitmap Filter33(Bitmap image, byte[,] mask, double scale)
        {
            int imageWidth = image.Width, imageHeight = image.Height;
            Bitmap result = new Bitmap(imageWidth, imageHeight);
            for (int i = 2; i < imageWidth - 1; i++)
                for (int j = 2; j < imageHeight - 1; j++)
                {
                    Byte red = 0, green = 0, blue = 0;
                    const Byte alpha = 255; // alpha is const !
                    for (int x = -1; x <= 1; x++)
                        for (int y = -1; y <= 1; y++)
                        {
                            Color pixel = image.GetPixel(i + x, j + y);
                            red += (byte)(pixel.R * mask[x + 1, y + 1]);
                            green += (byte)(pixel.G * mask[x + 1, y + 1]);
                            blue += (byte)(pixel.B * mask[x + 1, y + 1]);
                        }
                    Color newPixel = Color.FromArgb(
                        alpha,
                        Math.Abs((int)(red / scale)),
                        Math.Abs((int)(green / scale)),
                        Math.Abs((int)(blue / scale)));
                    result.SetPixel(i, j, newPixel);
                }
            return result;
        }
    }
}


Работайте отладчиком! smile 

Присоединённый файл ( Кол-во скачиваний: 20 )
Присоединённый файл  ImageFilter33.rar 34,11 Kb


--------------------
ἀπὸ μηχανῆς θεός
PM MAIL ICQ GTalk   Вверх
marcusmae
Дата 3.6.2008, 23:01 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


stravaganza
**


Профиль
Группа: Участник
Сообщений: 874
Регистрация: 26.3.2006

Репутация: 22
Всего: 39



Хм, кажется, понял, в чём дело : когда Вы складываете суммы для осреднения в red, green, blue, идёт превышение диапазона значений типа byte, т.е. идёт переход через максимум в минимум. Расширяем тип :

Код

                    int red = 0, green = 0, blue = 0, alpha = 0;
                    for (int x = -1; x <= 1; x++)
                        for (int y = -1; y <= 1; y++)
                        {
                            Color pixel = image.GetPixel(i + x, j + y);
                            red += pixel.R * mask[x + 1, y + 1];
                            green += pixel.G * mask[x + 1, y + 1];
                            blue += pixel.B * mask[x + 1, y + 1];
                            alpha += pixel.A;
                        }
                    result.SetPixel(i, j, Color.FromArgb(
                        (int)(alpha / scale),
                        (int)(red / scale),
                        (int)(green / scale),
                        (int)(blue / scale)));


исходное/полученное 
user posted imageuser posted image

9-точечный фильтр smile Ещё бы углы осреднить по сокращённым формулам...

Кстати, при взятии элементов массива маски была ошибка в индексах :

Цитата

                        Red=Red+red_buf[i+x][j+y]*mask3[x+2][y+2];
                        Green=Green+green_buf[i+x][j+y]*mask3[x+2][y+2];
                        Blue=Blue+blue_buf[i+x][j+y]*mask3[x+2][y+2];


Это сообщение отредактировал(а) marcusmae - 3.6.2008, 23:05


--------------------
ἀπὸ μηχανῆς θεός
PM MAIL ICQ GTalk   Вверх
emike
Дата 4.6.2008, 17:34 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Новичок



Профиль
Группа: Участник
Сообщений: 7
Регистрация: 30.5.2008

Репутация: нет
Всего: нет



marcusmae, спасибо - буду разбираться


Разобрался, вроде работает   smile 

 Кстати, scale все-таки надо брать 9 (для фильтра 5х5: scale = 25) - так по теории и на практике тоже.

Спасибо еще раз  smile 

Это сообщение отредактировал(а) emike - 4.6.2008, 18:47
PM MAIL   Вверх
marcusmae
Дата 4.6.2008, 21:35 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


stravaganza
**


Профиль
Группа: Участник
Сообщений: 874
Регистрация: 26.3.2006

Репутация: 22
Всего: 39



Цитата(emike @  4.6.2008,  17:34 Найти цитируемый пост)
Кстати, scale все-таки надо брать 9 (для фильтра 5х5: scale = 25) - так по теории и на практике тоже.


Да-да, конечно. Просто надо было какой-то из параметров пошевелить, чтобы проанализировать изменчивость результата smile У себя поправил обратно :
Код

const double scale = 9;

Картинки построены именно для 9.


--------------------
ἀπὸ μηχανῆς θεός
PM MAIL ICQ GTalk   Вверх
  
Ответ в темуСоздание новой темы Создание опроса
Прежде чем создать тему, посмотрите сюда:
mr.DUDA
THandle

Используйте теги [code=csharp][/code] для подсветки кода. Используйтe чекбокс "транслит" если у Вас нет русских шрифтов.
Что делать если Вам помогли, но отблагодарить помощника плюсом в репутацию Вы не можете(не хватает сообщений)? Пишите сюда, или отправляйте репорт. Поставим :)
Так же не забывайте отмечать свой вопрос решенным, если он таковым является :)


Если Вам понравилась атмосфера форума, заходите к нам чаще! С уважением, mr.DUDA, THandle.

 
1 Пользователей читают эту тему (1 Гостей и 0 Скрытых Пользователей)
0 Пользователей:
« Предыдущая тема | Общие вопросы по .NET и C# | Следующая тема »


 




[ Время генерации скрипта: 0.0721 ]   [ Использовано запросов: 21 ]   [ GZIP включён ]


Реклама на сайте     Информационное спонсорство

 
По вопросам размещения рекламы пишите на vladimir(sobaka)vingrad.ru
Отказ от ответственности     Powered by Invision Power Board(R) 1.3 © 2003  IPS, Inc.