.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; } } }
ИИ поможет Вам:
- решить любую задачу по программированию
- объяснить код
- расставить комментарии в коде
- и т.д