Форум программистов, компьютерный форум, киберфорум
C# .NET
Войти
Регистрация
Восстановить пароль
Блоги Сообщество Поиск Заказать работу  
 
Рейтинг 4.81/21: Рейтинг темы: голосов - 21, средняя оценка - 4.81
Level 2
 Аватар для FakiR
401 / 275 / 48
Регистрация: 22.11.2010
Сообщений: 785
Записей в блоге: 1
.NET 4.x

Поиск соседних пикселей

24.08.2011, 15:55. Показов 4071. Ответов 13
Метки нет (Все метки)

Студворк — интернет-сервис помощи студентам
Мне нужно получить цвет соседних пикселей (GetPixel). Это впринцепе почти тоже что и поиск соседних элементов в матрице, но примера на C# не смог найти, только VB. Если у кого то имеется готовое решение или есть желание помочь, буду очень признателен.
P.S. - Не первый раз сталкиваюсь с данной проблемой, каждый раз новый код получался, но ни одного красивого и одновременно быстрого способа не нашёл... Вот есть такой код, но он у меня выполняется слишком долго (много минут, даже не дождался завершения)... Предположительно там долго из-за того что исопльзую catch, но иначе не знаю как сделать...
P.P.S. - Просто экспериментирую...

C#
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
        private Color GetAverage(int x, int y) //Метод для получения среднего значения цвета соседних пикселей, x и y - пиксель соседей которого нужно найти
        {
            int R = 0, G = 0, B = 0;
            int[,] Mas = { { -1, -1 },  //Сложно объяснить, но это я использовал чтобы находить соседние пиксели
                           {  0, -1 },
                           {  1, -1 },
                           {  1,  0 },
                           {  1,  1 },
                           {  0,  1 },
                           { -1,  1 },
                           { -1,  0 } };
            for (int i = 0; i < Mas.Length; i++)
            {
                try //Если такого пикселя не существует, то ничего не происходит
                {
                    R = bm.GetPixel(x + Mas[i, 0], y + Mas[i, 1]).R;
                    G = bm.GetPixel(x + Mas[i, 0], y + Mas[i, 1]).G;
                    B = bm.GetPixel(x + Mas[i, 0], y + Mas[i, 1]).B;
                }
                catch { }
            }
            return Color.FromArgb(R / 8, G / 8, B / 8);
        }
Заранее спасибо!
0
cpp_developer
Эксперт
20123 / 5690 / 1417
Регистрация: 09.04.2010
Сообщений: 22,546
Блог
24.08.2011, 15:55
Ответы с готовыми решениями:

Поиск групп пикселей в изображении
Всем привет. Хочу посоветоваться в решении задачи. Есть сканированное изображение. Это изображение представляет собой просто фон с...

Поиск определенных пикселей на экране и эмуляция кликов мыши
Привет всем, нужна помощь! Вообщем смотрим: Итак преступим. Для начала нам нужно импортировать нужные WinApi функции: static...

Обработка изображения: поиск пикселей определённого цвета
Добрый вечер! Имеется такое задание: есть изображение, нужно найти пиксели определенного цвета и записать их координаты в массив. В...

13
 Аватар для umnick_kh
311 / 249 / 44
Регистрация: 06.12.2010
Сообщений: 527
24.08.2011, 16:07
FakiR, сама по себе функция GetPixel, да и SetPixel, очень долгие. Я тоже с этим сталкивался. Мне дали несколько решений:
Аналоги для GetPixel/SetPixel
1
Level 2
 Аватар для FakiR
401 / 275 / 48
Регистрация: 22.11.2010
Сообщений: 785
Записей в блоге: 1
24.08.2011, 16:41  [ТС]
Большое спасибо, щас буду пробовать

Добавлено через 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
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
unsafe class BufferedBitmap
        {
            Bitmap _bmp;
            BitmapData _bd;
            bool _locked;
            byte* pStart;
 
            public BufferedBitmap(Bitmap bmp, bool @lock)
            {
                _bmp = bmp;
                if (@lock)
                    Lock();
            }
 
            public BufferedBitmap(Bitmap bmp) : this(bmp, true) { }
 
            public void Lock()
            {
                if (!_locked)
                {
                    _bd = _bmp.LockBits(new Rectangle(0, 0, _bmp.Width, _bmp.Height), ImageLockMode.ReadWrite, _bmp.PixelFormat);
                    pStart = (byte*)_bd.Scan0;
                    _locked = true;
                }
            }
 
            public void Unlock()
            {
                if (!_locked)
                    return;
                _bmp.UnlockBits(_bd);
                _locked = false;
            }
 
            public Bitmap Bitmap
            {
                get
                {
                    return (_locked ? null : _bmp);
                }
                set
                {
                    if (_locked)
                        throw new Exception("Image locked!");
                    if (value == null)
                        throw new NullReferenceException();
                    _bmp = value;
                }
            }
 
            public int Width
            {
                get
                {
                    return _bmp.Width;
                }
            }
 
            public int Height
            {
                get
                {
                    return _bmp.Height;
                }
            }
 
            public void SetPixel(int x, int y, Color clr)
            {
                if (!_locked)
                    throw new Exception();
                switch (_bd.PixelFormat)
                {
                    case PixelFormat.Format24bppRgb:
                        SetPixel24(x, y, clr);
                        break;
                    case PixelFormat.Format32bppArgb:
                        SetPixel32(x, y, clr);
                        break;
                }
            }
 
            void SetPixel24(int x, int y, Color clr)
            {
                var pMem = pStart + x * 3 + y * _bd.Stride;
                *pMem = clr.B;
                *(pMem + 1) = clr.G;
                *(pMem + 2) = clr.R;
            }
 
            void SetPixel32(int x, int y, Color clr)
            {
                var pMem = pStart + x * 4 + y * _bd.Stride;
                *pMem = clr.B;
                *(pMem + 1) = clr.G;
                *(pMem + 2) = clr.R;
                *(pMem + 3) = clr.A;
            }
 
            public Color GetPixel(int x, int y)
            {
                if (!_locked)
                    throw new Exception();
                switch (_bd.PixelFormat)
                {
                    case PixelFormat.Format24bppRgb:
                        return GetPixel24(x, y);
                    case PixelFormat.Format32bppArgb:
                        return GetPixel32(x, y);
                    default:
                        throw new NotImplementedException();
                }
            }
 
            Color GetPixel24(int x, int y)
            {
                var pMem = pStart + x * 3 + y * _bd.Stride;
                return Color.FromArgb(*(pMem + 2), *(pMem + 1), *pMem);
            }
 
            Color GetPixel32(int x, int y)
            {
                var pMem = pStart + x * 4 + y * _bd.Stride;
                return Color.FromArgb(*(pMem + 3), *(pMem + 2), *(pMem + 1), *pMem);
            }
 
            public bool IsLocked
            {
                get
                {
                    return _locked;
                }
            }
        }
И получил вот такую ошибку:

Ошибка 1 Небезопасный код может использоваться только при компиляции с параметром /unsafe C:\Users\FakiR\Desktop\SetPixel\WindowsF ormsApplication1\Form1.cs 79 22 WindowsFormsApplication1

Что не так?

Добавлено через 12 минут
Разобрался, надо было в свойствах проекта разрешить использование unsafe кода.
0
Почетный модератор
Эксперт .NET
 Аватар для NickoTin
8725 / 3677 / 404
Регистрация: 14.06.2010
Сообщений: 4,513
Записей в блоге: 9
24.08.2011, 16:51
FakiR, этот код можно немного оптимизировать:
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
unsafe class BufferedBitmap : IDisposable
{
    delegate void SetPixelInternal ( int x, int y, Color clr );
    delegate Color GetPixelInternal ( int x, int y );
 
    Bitmap _bmp;
    BitmapData _bd;
    bool _locked;
    byte *pStart;
 
    SetPixelInternal setPix;
    GetPixelInternal getPix;
 
    public BufferedBitmap ( Bitmap bmp, bool @lock ) {
        _bmp = bmp;
 
        if ( @lock )
            Lock();
    }
 
    public BufferedBitmap ( Bitmap bmp )
        : this( bmp, true ) {
 
    }
 
    public void Lock ( ) {
        if ( !_locked ) {
            _bd = _bmp.LockBits(
                new Rectangle( 0, 0, _bmp.Width, _bmp.Height ),
                ImageLockMode.ReadWrite,
                _bmp.PixelFormat
            );
 
            pStart = (byte*)_bd.Scan0;
            _locked = true;
 
            switch ( _bmp.PixelFormat ) {
            case PixelFormat.Format24bppRgb:
                setPix = SetPixel24;
                getPix = GetPixel24;
                break;
            case PixelFormat.Format32bppArgb:
                setPix = SetPixel32;
                getPix = GetPixel32;
                break;
            default:
                throw new NotImplementedException();
            }
        }
    }
 
    public void Unlock ( ) {
        if ( !_locked )
            return;
 
        _bmp.UnlockBits( _bd );
 
        getPix = null;
        setPix = null;
        _locked = false;
    }
 
    public Bitmap Bitmap {
        get {
            return ( _locked ? null : _bmp );
        }
        set {
            if ( _locked )
                throw new Exception( "Image locked!" );
            if ( value == null )
                throw new NullReferenceException();
 
            _bmp = value;
        }
    }
 
    public int Width {
        get {
            return _bmp.Width;
        }
    }
 
    public int Height {
        get {
            return _bmp.Height;
        }
    }
 
    public void SetPixel ( int x, int y, Color clr ) {
        if ( !_locked )
            throw new Exception();
 
        setPix( x, y, clr );
    }
 
    void SetPixel24 ( int x, int y, Color clr ) {
        var pMem = pStart + x * 3 + y * _bd.Stride;
 
        *pMem = clr.B;
        *( pMem + 1 ) = clr.G;
        *( pMem + 2 ) = clr.R;
    }
 
    void SetPixel32 ( int x, int y, Color clr ) {
        var pMem = pStart + x * 4 + y * _bd.Stride;
 
        *pMem = clr.B;
        *( pMem + 1 ) = clr.G;
        *( pMem + 2 ) = clr.R;
        *( pMem + 3 ) = clr.A;
    }
 
    public Color GetPixel ( int x, int y ) {
        if ( !_locked )
            throw new Exception();
 
        return getPix( x, y );
    }
 
    Color GetPixel24 ( int x, int y ) {
        var pMem = pStart + x * 3 + y * _bd.Stride;
 
        return Color.FromArgb(
            *( pMem + 2 ),
            *( pMem + 1 ),
            *pMem
        );
    }
 
    Color GetPixel32 ( int x, int y ) {
        var pMem = pStart + x * 4 + y * _bd.Stride;
 
        return Color.FromArgb(
            *( pMem + 3 ),
            *( pMem + 2 ),
            *( pMem + 1 ),
            *pMem
        );
    }
 
    public bool IsLocked {
        get {
            return _locked;
        }
    }
 
    public void Dispose ( ) {
        if ( _locked )
            Unlock();
    }
}
1
Level 2
 Аватар для FakiR
401 / 275 / 48
Регистрация: 22.11.2010
Сообщений: 785
Записей в блоге: 1
24.08.2011, 17:30  [ТС]
Спасибо, но возникла проблема... Использую класс следующим образом:

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
BufferedBitmap temp_bm = null;
 
private void Form1_Load(object sender, EventArgs e)
        {
            temp_bm = new BufferedBitmap(bm);
        }
 
private void Method()
        {
            for (int i = 0; i < bm.VerticalResolution * 4.6875; i++)
                for (int j = 0; j < bm.HorizontalResolution * 4.6875; j++)
                    temp_bm.SetPixel(j, i, GetAverage(i, j));
        }
 
private Color GetAverage(int x, int y)
        {
            ...
            for (int i = 0; i < Mas.GetLength(0); i++)
            {
                try
                {
                    R += temp_bm.GetPixel(x + Mas[i, 0], y + Mas[i, 1]).R;
                    G += temp_bm.GetPixel(x + Mas[i, 0], y + Mas[i, 1]).G;
                    B += temp_bm.GetPixel(x + Mas[i, 0], y + Mas[i, 1]).B;
                }
                catch { }
            }
            return Color.FromArgb(R / 8, G / 8, B / 8);
        }
Так вот, при использовании метода GetPixel в методе GetAverage возникает Exception (AccessViolationException):

Попытка чтения или записи в защищенную память. Это часто свидетельствует о том, что другая память повреждена.

А конкретно возникает в методе класса:

C#
1
2
3
4
5
Color GetPixel32(int x, int y)
        {
            var pMem = pStart + x * 4 + y * _bd.Stride;
            return Color.FromArgb(*(pMem + 3), *(pMem + 2), *(pMem + 1), *pMem); //Вот тут
        }
Проверял пошагово и заметил что он не сразу исключение показывает... Может я не правильно как то использую класс?

P.S. - SetPixel работает без ошибок вроде.

Добавлено через 13 минут
Попробовал использовать другой класс, но появляется тот же Exception...
0
Почетный модератор
Эксперт .NET
 Аватар для NickoTin
8725 / 3677 / 404
Регистрация: 14.06.2010
Сообщений: 4,513
Записей в блоге: 9
24.08.2011, 17:36
FakiR, минус данных реализаций (unsafe) в том что могут появляться плавающие ошибки. Ошибка в том что происходит выход за пределы выделенной под изображение памяти, т.е. слишком большие x и y, за счет этого неверно выполняется расчет смещения в памяти (pStart + x * 4 + y * _bd.Stride). Тут надо смотреть на месте... я пока не смог добиться AccesViolation, просто проходя по всему изображению и задавая цвет.
C#
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
            using ( var bmp = new Bitmap( 15, 67, PixelFormat.Format32bppArgb ) ) {
                Stopwatch sw;
                using ( var bb = new BufferedBitmap( bmp ) ) {
                    sw = Stopwatch.StartNew();
                    for ( int x = 0; x < bmp.Width; ++x )
                        for ( int y = 0; y < bmp.Height; ++y ) {
                            bb.SetPixel( x, y, Color.Red );
                            bb.SetPixel( 
                                x, y, Color.FromArgb( 
                                    bb.GetPixel( x, y ).ToArgb() ^ new Random().Next( 0, 1024 ) 
                                ) 
                            );
                        }
                    sw.Stop();
                    Trace.WriteLine( sw.ElapsedTicks );
                }
 
                bmp.Save( "C:\\temp.png", ImageFormat.Png );
            }
т.е. ошибка может быть здесь: x + Mas[i, 0], y + Mas[i, 1]
1
Level 2
 Аватар для FakiR
401 / 275 / 48
Регистрация: 22.11.2010
Сообщений: 785
Записей в блоге: 1
24.08.2011, 17:43  [ТС]
У меня тоже задаёт (SetPixel) цвет без проблем, а вот при попытке получения (GetPixel) возникают проблемы...

Да и x с y у меня не такие большие (450 максимум). Хотя если учитывать умножения всякие (pStart + x * 4 + y * _bd.Stride), то может это и много получается.
0
Почетный модератор
Эксперт .NET
 Аватар для NickoTin
8725 / 3677 / 404
Регистрация: 14.06.2010
Сообщений: 4,513
Записей в блоге: 9
24.08.2011, 18:11
FakiR, сколько не пробовал, исключение получить не удалось. Проверь в отладчике, какие у тебя получается x и y во время исключения, они должны быть меньше Width и Height изображения, если >= значит ошибка в x + Mas[i, 0], y + Mas[i, 1].
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
using ( var bmp = new Bitmap( 450, 450, PixelFormat.Format32bppArgb ) ) {
    Stopwatch sw;
    Random rnd;
 
    int width = (int)( bmp.HorizontalResolution * 4.6875 );
    int height = (int)( bmp.VerticalResolution * 4.6875 );
 
    using ( var bb = new BufferedBitmap( bmp ) ) {
        sw = Stopwatch.StartNew();
        for ( int x = 0; x < width; ++x )
            for ( int y = 0; y < height; ++y ) {
                rnd = new Random( DateTime.Now.Millisecond );
                bb.SetPixel(
                    x, y, Color.FromArgb(
                        rnd.Next( 0, 255 ),
                        rnd.Next( 0, 255 ),
                        rnd.Next( 0, 255 )
                    )
                );
                bb.SetPixel(
                    x, y, Color.FromArgb(
                        bb.GetPixel( x, y ).ToArgb() ^
                        rnd.Next( int.MinValue, int.MaxValue )
                    )
                );
            }
        sw.Stop();
        Trace.WriteLine( sw.ElapsedTicks );
    }
 
    bmp.Save( "C:\\temp.png", ImageFormat.Png );
}
Добавлено через 9 минут
А ответ прост оказался
C#
1
2
// Разрешение по горизонтали != длина изображения
bmp.HorizontalResolution /* == 96.0 */ * 4.6875 != bmp.Width
из-за этого и ошибки. Я создал изображение размером 100x100 и получил ошибку, хотя длина используемым Вами способом получалась 450. FakiR, используй bmp.Width и bmp.Height вместо Resolution.
1
Level 2
 Аватар для FakiR
401 / 275 / 48
Регистрация: 22.11.2010
Сообщений: 785
Записей в блоге: 1
24.08.2011, 20:18  [ТС]
В общем у меня возникало исключение из-за того что x был равен 450 (т.е. равен ширине). В общем переделал цикл так чтобы не проверялись крайние пиксели. теперь работает отлично. SSTREGG, спасибо! Ну и umnick_kh конечно спасибо
P.S. - Работает действительно в сотню раз быстрее. За долю секунды всё происходит.

Добавлено через 31 минуту
Странно, но всё равно иногда выскакивает это исключение... Ну да ладно.
0
Level 2
 Аватар для FakiR
401 / 275 / 48
Регистрация: 22.11.2010
Сообщений: 785
Записей в блоге: 1
25.08.2011, 17:33  [ТС]
Опять появилась проблема с классом... Всё тот же AccessViolationException. Я выложу проект, в него вложу пару изображений с которыми я работал. Если у кого есть желание помочь, буду благодарен.

P.S. - На больших изображениях вылетает Exception, а на более маленьких Exception не вылетает, но они обрабатываются не полностью и как то странно местами... Если обрабатывать изображения размерами примерно 450x450 то всё отлично. Не могу понять почему так происходит...

P.P.S. - Значения x и y превышают размеры изображения во время исключения, но не пойму почему так происходит...

Desktop.rar

Использование программы: выбираем изображение, выбираем цвет, нажимает кнопку применить.
0
Level 2
 Аватар для FakiR
401 / 275 / 48
Регистрация: 22.11.2010
Сообщений: 785
Записей в блоге: 1
25.08.2011, 17:40  [ТС]
Кстати, забыл прокомментировать код, так что если что то не понятно, спрашивайте.
0
Почетный модератор
Эксперт .NET
 Аватар для NickoTin
8725 / 3677 / 404
Регистрация: 14.06.2010
Сообщений: 4,513
Записей в блоге: 9
25.08.2011, 18:34
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
        private void Blur ( ) {
            Temp_bm.Lock();
            Color UserColor = colorDialog1.Color;
            for ( int i = 0; i < Img.Width; i++ ) // Вот в этих 2х строчках
                for ( int j = 0; j < Img.Height; j++ ) /* была ошибка */ {
                    Color Old = Temp_bm.GetPixel( i, j ); //Старый цвет пикселя
                    int NewR = Old.R < UserColor.R ? UserColor.R - Old.R : Old.R - UserColor.R;   //Вычисление
                    int NewG = Old.G < UserColor.G ? UserColor.G - Old.G : Old.G - UserColor.G; //нового цвета
                    int NewB = Old.B < UserColor.B ? UserColor.B - Old.B : Old.B - UserColor.B;      //пикселя
                    Temp_bm.SetPixel( i, j, Color.FromArgb( NewR, NewG, NewB ) );
                }
            Temp_bm.Unlock();
        }
 
        private void LoadImage ( ) {
            try {
                if ( Img != null )
                    Img.Dispose();
                Img = new Bitmap( openFileDialog1.FileName );
                if ( Temp_bm != null && Temp_bm.IsLocked )
                    Temp_bm.Unlock();
                else
                    Temp_bm = new BufferedBitmap( Img, false );
                //this.Size = new Size( Img.Width, Img.Height );
                CenterToScreen();
                lbl_Resolution.Text = Img.Width + "x" + Img.Height;
            } catch {
                this.BackColor = SystemColors.ActiveCaption;
            }
            this.BackgroundImage = Img;
        }
1
 Аватар для Unril
826 / 717 / 110
Регистрация: 06.10.2010
Сообщений: 825
Записей в блоге: 1
25.08.2011, 20:06
Пример быстрой обработки изображения с помощью фильтра:
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
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Drawing;
using System.Drawing.Imaging;
using System.Linq;
using System.Runtime.InteropServices;
using System.Threading.Tasks;
using System.Windows.Forms;
 
namespace WindowsFormsTest {
    public sealed partial class Form1 : Form {
        private Bitmap _bitmap;
        private Bitmap _originalBitmap;
 
        public Form1() {
            InitializeComponent();
            Load += OnLoad;
        }
 
        private void OnLoad( object sender, EventArgs eventArgs ) {
            const string path = "test.jpeg";
 
            _originalBitmap = new Bitmap( path );
            pictureBox1.Image = _originalBitmap;
            _bitmap = (Bitmap)_originalBitmap.Clone();
        }
 
        private void buttonStart_Click( object sender, EventArgs e ) {
            var kernel = new[,] {
                { textBox1.Text, textBox2.Text, textBox3.Text },
                { textBox4.Text, textBox5.Text, textBox6.Text },
                { textBox7.Text, textBox8.Text, textBox9.Text },
            }.ForAll( s => int.Parse( s ) );
 
            Stopwatch stopwatch = Stopwatch.StartNew();
 
            _bitmap = ProcessBitmap( _bitmap, kernel );
 
            stopwatch.Stop();
 
            label1.Text = stopwatch.ElapsedMilliseconds.ToString();
            pictureBox1.Image = _bitmap;
        }
 
        private void buttonReset_Click( object sender, EventArgs e ) {
            _bitmap = _originalBitmap;
            pictureBox1.Image = _bitmap;
        }
 
        private static Bitmap ProcessBitmap( Bitmap input, int[,] kernelNonscaled ) {
            // Нормализуем ядро. Необходимо, чтобы сумма всех коэффициентов была равна единице.
            int kernelSum = kernelNonscaled.Flatten().Sum();
            var kernel = kernelNonscaled.ForAll( n => n/(double)kernelSum );
 
            int width = input.Width;
            int height = input.Height;
 
            Rectangle rectangle = new Rectangle( 0, 0, width, height );
 
            // Блокируем изображения в памяти.
            BitmapData inputData = input.LockBits( rectangle, ImageLockMode.ReadOnly, input.PixelFormat );
 
            // Создаём массивы с цветовыми составляющими.
            int bytesCount = inputData.Stride*height;
            var brgInput = new byte[bytesCount];
            var brgOutput = new byte[bytesCount];
 
            // Копируем цвета в исходный массив.
            Marshal.Copy( inputData.Scan0, brgInput, 0, bytesCount );
            input.UnlockBits( inputData );
 
            // Применяем фильтр ко всем пикселям.
            int stride = inputData.Stride;
            Parallel.For( 1, height - 1, y => {
                for ( int d = 0; d < 3; d++ ) {
                    for ( int x = 1; x < width - 1; x++ ) {
                        double result =
                            kernel[ 0, 0 ]*brgInput[ Pos( stride, x - 1, y - 1, d ) ] +
                            kernel[ 0, 1 ]*brgInput[ Pos( stride, x - 1, y, d ) ] +
                            kernel[ 0, 2 ]*brgInput[ Pos( stride, x - 1, y + 1, d ) ] +
                            kernel[ 1, 0 ]*brgInput[ Pos( stride, x, y - 1, d ) ] +
                            kernel[ 1, 1 ]*brgInput[ Pos( stride, x, y, d ) ] +
                            kernel[ 1, 2 ]*brgInput[ Pos( stride, x, y + 1, d ) ] +
                            kernel[ 2, 0 ]*brgInput[ Pos( stride, x + 1, y - 1, d ) ] +
                            kernel[ 2, 1 ]*brgInput[ Pos( stride, x + 1, y, d ) ] +
                            kernel[ 2, 2 ]*brgInput[ Pos( stride, x + 1, y + 1, d ) ];
 
                        int currentPosition = Pos( stride, x, y, d );
                        if ( result < 0 ) {
                            brgOutput[ currentPosition ] = 0;
                        }
                        else if ( result > 255 ) {
                            brgOutput[ currentPosition ] = 255;
                        }
                        else {
                            brgOutput[ currentPosition ] = (byte)result;
                        }
                    }
                }
            } );
 
            // Создаём выходное изображение и копируем полученный массив в него.
            Bitmap output = new Bitmap( width, height, input.PixelFormat );
            BitmapData outputData = output.LockBits( rectangle, ImageLockMode.WriteOnly, output.PixelFormat );
            Marshal.Copy( brgOutput, 0, outputData.Scan0, bytesCount );
            output.UnlockBits( outputData );
 
            return output;
        }
 
        private static int Pos( int stride, int x, int y, int d ) {
            return y*stride + x*3 + d;
        }
    }
 
    public static class Extensions {
        public static IEnumerable<T> Flatten<T>( this T[,] arr ) {
            for ( int i = 0; i < arr.GetLength( 0 ); i++ ) {
                for ( int j = 0; j < arr.GetLength( 1 ); j++ ) {
                    yield return arr[ i, j ];
                }
            }
        }
 
        public static TOut[,] ForAll<TIn, TOut>( this TIn[,] arr, Func<TIn, TOut> func ) {
            int n = arr.GetLength( 0 );
            int m = arr.GetLength( 1 );
            var result = new TOut[n,m];
 
            for ( int i = 0; i < n; i++ ) {
                for ( int j = 0; j < m; j++ ) {
                    result[ i, j ] = func( arr[ i, j ] );
                }
            }
 
            return result;
        }
    }
}
На форме накиданы pictureBox1, пара кнопок, и матрица 3х3 из текст боксов. Обработка изображения 1000х600 пикселей занимает 120мс.
2
Level 2
 Аватар для FakiR
401 / 275 / 48
Регистрация: 22.11.2010
Сообщений: 785
Записей в блоге: 1
25.08.2011, 20:33  [ТС]
Unril, спасибо, попробую позже
SSTREGG, ещё раз спасибо, как всегда невнимательность губит...
0
Надоела реклама? Зарегистрируйтесь и она исчезнет полностью.
raxper
Эксперт
30234 / 6612 / 1498
Регистрация: 28.12.2010
Сообщений: 21,154
Блог
25.08.2011, 20:33
Помогаю со студенческими работами здесь

Поиск пикселей определенного цвета на двух или более изображениях одного размера и отрисовка их на первом
Появилась необходимость написать простенькую программу целькоторой будет: Поиск пикселей определенного цвета на 2х или более изображениях...

Поиск пикселей в изображении
В общем ситуация такая: нужно получить скрин экрана и найти координаты пикселей определённого цвета, к примеру белого. И это должно...

Поиск пикселей в изображении
Реализовал поиск в изображении через Image1-&gt;Canvas-&gt;Pixel Но проблема в том, что такое поиск занимает очень много времени... Есть...

Поиск соседних точек
Доброго времени суток! Строится график, а именно круг с полярной сеткой, все точки я собираю в массив. Кликнув на график появляются...

Поиск соседних одинаковых элементов
Доброго времени суток! Есть такая задачка: существует массив 8х8, вводятся i,j индексы и если эти индексы указывают на элемент соседи...


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

Или воспользуйтесь поиском по форуму:
14
Ответ Создать тему
Новые блоги и статьи
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 Использованы. . .
SDL3 для Android: Загрузка PNG с альфа-каналом с помощью SDL_LoadPNG (без SDL3_image)
8Observer8 28.01.2026
Содержание блога SDL3 имеет собственные средства для загрузки и отображения PNG-файлов с альфа-каналом и базовой работы с ними. В этой инструкции используется функция SDL_LoadPNG(), которая. . .
КиберФорум - форум программистов, компьютерный форум, программирование
Powered by vBulletin
Copyright ©2000 - 2026, CyberForum.ru