Форум программистов, компьютерный форум, киберфорум
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. Показов 4083. Ответов 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
8728 / 3680 / 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
8728 / 3680 / 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
8728 / 3680 / 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
8728 / 3680 / 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): Синхронизация спрайтов SDL3 и тел Box2D
8Observer8 04.03.2026
Содержание блога Финальная демка в браузере. Итоговый код: finish-sync-physics-sprites-sdl3-c. zip На первой гифке отладочные линии отключены, а на второй включены:. . .
SDL3 для Web (WebAssembly): Идентификация объектов на Box2D v3 - использование userData и событий коллизий
8Observer8 02.03.2026
Содержание блога Финальная демка в браузере. Итоговый код: finish-collision-events-sdl3-c. zip https:/ / www. cyberforum. ru/ blog_attachment. php?attachmentid=11680&amp;d=1772460536 Одним из. . .
Реалии
Hrethgir 01.03.2026
Нет, я не закончил до сих пор симулятор. Эта задача сложнее. Не получилось уйти в плавсостав, но оно и к лучшему, возможно. Точнее получалось - но сварщиком в палубную команду, а это значит, в моём. . .
Ритм жизни
kumehtar 27.02.2026
Иногда приходится жить в ритме, где дел становится всё больше, а вовлечения в происходящее — всё меньше. Плотный график не даёт вниманию закрепиться ни на одном событии. Утро начинается с быстрых,. . .
SDL3 для Web (WebAssembly): Сборка библиотек: SDL3, Box2D, FreeType, SDL3_ttf, SDL3_mixer и SDL3_image из исходников с помощью CMake и Emscripten
8Observer8 27.02.2026
Недавно вышла версия 3. 4. 2 библиотеки SDL3. На странице официальной релиза доступны исходники, готовые DLL (для x86, x64, arm64), а также библиотеки для разработки под Android, MinGW и Visual Studio. . . .
SDL3 для Web (WebAssembly): Реализация движения на Box2D v3 - трение и коллизии с повёрнутыми стенами
8Observer8 20.02.2026
Содержание блога Box2D позволяет легко создать главного героя, который не проходит сквозь стены и перемещается с заданным трением о препятствия, которые можно располагать под углом, как верхнее. . .
Конвертировать закладки radiotray-ng в m3u-плейлист
damix 19.02.2026
Это можно сделать скриптом для PowerShell. Использование . \СonvertRadiotrayToM3U. ps1 <path_to_bookmarks. json> Рядом с файлом bookmarks. json появится файл bookmarks. m3u с результатом. # Check if. . .
Семь CDC на одном интерфейсе: 5 U[S]ARTов, 1 CAN и 1 SSI
Eddy_Em 18.02.2026
Постепенно допиливаю свою "многоинтерфейсную плату". Выглядит вот так: https:/ / www. cyberforum. ru/ blog_attachment. php?attachmentid=11617&stc=1&d=1771445347 Основана на STM32F303RBT6. На борту пять. . .
КиберФорум - форум программистов, компьютерный форум, программирование
Powered by vBulletin
Copyright ©2000 - 2026, CyberForum.ru