.NET 4.x Поиск соседних пикселей - C#

Узнай цену своей работы

Формулировка задачи:

Мне нужно получить цвет соседних пикселей (GetPixel). Это впринцепе почти тоже что и поиск соседних элементов в матрице, но примера на C# не смог найти, только VB. Если у кого то имеется готовое решение или есть желание помочь, буду очень признателен. P.S. - Не первый раз сталкиваюсь с данной проблемой, каждый раз новый код получался, но ни одного красивого и одновременно быстрого способа не нашёл... Вот есть такой код, но он у меня выполняется слишком долго (много минут, даже не дождался завершения)... Предположительно там долго из-за того что исопльзую catch, но иначе не знаю как сделать... P.P.S. - Просто экспериментирую...
        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);
        }
Заранее спасибо!

Решение задачи: «.NET 4.x Поиск соседних пикселей»

textual
Листинг программы
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;
        }
    }
}

ИИ поможет Вам:


  • решить любую задачу по программированию
  • объяснить код
  • расставить комментарии в коде
  • и т.д
Попробуйте бесплатно

Оцени полезность:

8   голосов , оценка 4.25 из 5
Похожие ответы