Member 13341679 Ответов: 0

Как динамически добавить новую матрицу к изображению


Здравствуйте, я работаю над обработкой изображений(проектированием пользовательского интерфейса) с помощью C#.Net и против 2012 года. Я добавил фильтр свертки в свою форму. Я добавил матрицу ядра в бэк-конец, но теперь я хочу добавить новые матрицы(любого размера-3*3, 5*5, 7*7 и т. д.) Во время выполнения. Я не знаю, что и как делать. Кто-нибудь может мне помочь, пожалуйста.
(Когда мы нажимаем на кнопку свертки, появляется новая форма и просит ввести новую матрицу. Здесь я сталкиваюсь с проблемой, я не могу спроектировать формат для ввода матрицы в формате строки-столбца(создавая разные ячейки для ввода данных)).

Что я уже пробовал:

//Код для свертки
private static double[,] kernel
        {
            get
            {
                return new double[,]
                {
                    { 0, 1, 0 },
                    { 1, -4, 1 },
                    { 0, 1, 0 }
                };
            }
        }

        private void btnConvolution_Click(object sender, EventArgs e)
        {
                    newBitmap = (Bitmap)pictureBox1.Image;
                    int width = newBitmap.Width;
                    int height = newBitmap.Height;

                    BitmapData srcData = newBitmap.LockBits(new Rectangle(0, 0, width, height), ImageLockMode.ReadOnly, PixelFormat.Format32bppArgb);
                    int bytes = srcData.Stride * srcData.Height;

                    byte[] buffer = new byte[bytes];//new array
                    byte[] result = new byte[bytes];
                    Marshal.Copy(srcData.Scan0, buffer, 0, bytes);
                    newBitmap.UnlockBits(srcData);
                    int colorChannels = 3;//3 color channels
                    double[] rgb = new double[colorChannels];
                    int foff = (kernel.GetLength(0) - 1) / 2;
                    int kcenter = 0;
                    int kpixel = 0;

                    for (int y = foff; y < height - foff; y++)
                    {
                        for (int x = foff; x < width - foff; x++)
                        {
                            for (int c = 0; c < colorChannels; c++)
                            {
                                rgb[c] = 0.0;
                            }
                            kcenter = y * srcData.Stride + x * 4;
                            for (int fy = -foff; fy <= foff; fy++)
                            {
                                for (int fx = -foff; fx <= foff; fx++)
                                {
                                    kpixel = kcenter + fy * srcData.Stride + fx * 4;
                                    for (int c = 0; c < colorChannels; c++)
                                    {
                                        rgb[c] += (double)(buffer[kpixel + c]) * kernel[fy + foff, fx + foff];
                                    }
                                }
                            }
                            for (int c = 0; c < colorChannels; c++)
                            {
                                if (rgb[c] > 255)
                                {
                                    rgb[c] = 255;
                                }
                                else if (rgb[c] < 0)
                                {
                                    rgb[c] = 0;
                                }
                            }
                            for (int c = 0; c < colorChannels; c++)
                            {
                                result[kcenter + c] = (byte)rgb[c];
                            }
                            result[kcenter + 3] = 255;
                        }
                    }

                    Bitmap resultImage = new Bitmap(width, height);
                    BitmapData resultData = resultImage.LockBits(new Rectangle(0, 0, width, height),
                    ImageLockMode.WriteOnly, PixelFormat.Format32bppArgb);
                    Marshal.Copy(result, 0, resultData.Scan0, bytes);
                    resultImage.UnlockBits(resultData);

                    newBitmap = (Bitmap)resultImage.Clone();
                    pictureBox1.Image = newBitmap;
                    btnUndo.Enabled = true;
                    undostack.Push(pictureBox1.Image);
                }
        }

Richard MacCutchan

Вы можете использовать DataGridView необходимого количества строк и столбцов. Просто попросите пользователя заполнить цифры и нажать кнопку, когда закончите.

Member 13341679

Как он будет меняться в зависимости от размера матрицы, здесь размер матрицы также меняется. Как принять это значение в код для дальнейших вычислений.

Richard MacCutchan

Подумайте об этом в логических терминах:
Сколько строк вам нужно?
Сколько колонок вам нужно?
Попросите пользователя предоставить вам эту информацию.
Теперь вы можете создать сетку с необходимым количеством ячеек, пользователь может ввести значения, и из этого вы можете создать свою динамическую матрицу.

Member 13341679

Это пользовательский интерфейс, и пользователь может занять до 9*9 матриц(3*3,5*5,7*7,9*9 имеются в наличии). Поэтому, если я добавляю формат матрицы 9*9, а пользователь принимает 5*5, то значение будет пустым, и код не будет выполняться. Надеюсь, вы поняли, что я пытаюсь сказать.

Richard MacCutchan

Затем либо исправьте свой код, либо сделайте то, что я предложил. Ничто из этого не является особенно трудным при использовании .Чистый контроль.

lukeer

Таким образом, вам нужно, чтобы пользователь выбрал один из четырех возможных размеров ядра.
Все в порядке, ваше свойство ядра имеет тип double[,] Он должен быть в состоянии обрабатывать различные размеры. И код, который его использует, проверяет фактический размер ядра в int foff = (kernel.GetLength(0) - 1) / 2; В чем именно вы видите проблему?

Member 13341679

В коде нет никаких проблем. Здесь я сам назначил матрицу в соответствии с моим использованием, но я хочу сделать ее динамической, чтобы пользователь мог вставить матрицу по своему выбору. Я не знаю, как это сделать успешно.

lukeer

Дайте пользователю пользовательский интерфейс.
Вы могли бы поставить 4 Практическое руководствоs на бланке вместе с радиокнопкаs, которые указывают, какой из них использовать.
Затем пользователь может поместить свои предпочтительные значения фильтра в одну из сеток, вы бы сделали каждый ввод, чтобы также выбрать соответствующую сетку.
Затем эта форма отвечает за предоставление

public double[,] Kernel
{
    get
    {
        // export correct values
    }
}
собственность. И там у вас есть свои ценности.

0 Ответов