Работа с матрицей в emgu cv - PullRequest
1 голос
/ 26 августа 2011

У меня есть матрица (2D) изображения в EMGU cv, как я могу заполнить остальную часть матрицы нулями, но сохранить определенную область (прямоугольник) с исходными данными?

Ответы [ 2 ]

3 голосов
/ 26 августа 2011

Метод 1

Один из способов добиться того, что вам нужно, - получить прямой доступ к данным Матрицы и установить значения «0» в следующем коде.установит нижнюю четверть My_Matrix на 0, где все остальные значения останутся 20.

Matrix<double> My_Matrix_Image = new Matrix<double>(8,10);

My_Matrix_Image.SetValue(20);  //set all values of Matrix to 20

for(int i = 4; i< My_Matrix_Image.Height; i++)
{
    for (int j = 5; j < My_Matrix_Image.Width; j++)
    {
        My_Matrix_Image.Data[i,j] = 0; 
    }
}

Чтобы добиться того, что вы хотели от своего комментария, вы все равно должны использовать тот же подход, что My_Matrix_Image будет содержать значения данных вашего изображенияс 0-255 я дам решения как для оттенков серого, так и для цветных изображений.Я сохраню первые 30 строк изображения и установлю остальные на ноль, изображение будет 100x100 пикселей размером .Измените j = 30 , чтобы изменить количество строк.

Матрица изображения первого цвета будет иметь 3 канала Красный , Зеленый и Синий :

for(int i = 0; i< My_Matrix_Image.Height; i++)
{
    for (int j = 30; j < My_Matrix_Image.Width; j++)
    {
        My_Matrix_Image.Data[i,j,0] = 0; //RED
        My_Matrix_Image.Data[i,j,1] = 0; //GREEN
        My_Matrix_Image.Data[i,j,2] = 0; //BLUE

    }
}

Матрицы изображений в оттенках серого проще, поскольку будет 1 канал:

for(int i = 0; i< My_Matrix_Image.Height; i++)
{
    for (int j = 30; j < My_Matrix_Image.Width; j++)
    {
        My_Matrix_Image.Data[i,j,0] = 0; 
    }
}

Теперь предположим, что вы хотите сохранить Средние 40 строк вам придется добавить дополнительный цикл, помните, что это единственный способ с Matrix . Я предоставил только пример цветного изображения, так как вы можете видеть, что он начинает немного запутываться и Метод 2 может быть лучше:

for(int i = 0; i< My_Matrix_Image.Height; i++)
{
    //LOOP 1 SET THE FRONT ROWS
    for (int j = 0; j<40; j++)
    {
        My_Matrix_Image.Data[i,j,0] = 0; //RED
        My_Matrix_Image.Data[i,j,1] = 0; //GREEN
        My_Matrix_Image.Data[i,j,2] = 0; //BLUE
    }
    // LOOP 2 SET THE BACK ROWS
    for (int j = 60; j < My_Matrix_Image.Width; j++)
    {
        My_Matrix_Image.Data[i,j,0] = 0; //RED
        My_Matrix_Image.Data[i,j,1] = 0; //GREEN
        My_Matrix_Image.Data[i,j,2] = 0; //BLUE
    }
}

Метод 2

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

//Make a Blank Copy of your Image this will be automatically full of zeros
Matrix<double> My_Image_Copy = My_Image_Matrix.CopyBlank();

//Now copy the data you want to keep from your original image into you blank copy

for(int i = 40; i< 60; i++)
{
    for (int j = 40; j < 60; j++)
    {
        My_Image_Copy.Data[i,j,0] = My_Matrix_Image.Data[i,j,0]; //RED
        My_Image_Copy.Data[i,j,1] = My_Matrix_Image.Data[i,j,1]; //GREEN
        My_Image_Copy.Data[i,j,2] = My_Matrix_Image.Data[i,j,2]; //BLUE

    }
}

Приведенный выше код скопирует центр 20x20 пикселей из изображения, которое вы, очевидно, можете изменить, чтобы скопировать всестрок с использованием для (int i = 0; i

Намного лучше, я уверен, вы согласитесь.

Альтернатива

Теперь, когда вы используете матрицу для хранения ваших данных, используя конструкцию Image, кодирование становится немного проще.Хотя это может не относиться к вам, это может относиться к другим.

Если вы используете Image или альтернативу для хранения данных вашего изображения, это может быть достигнуто следующим образом:

Image<Gray, Byte> My_Image = new Image<Gray, byte>(openfile.FileName);
Image<Gray, Byte> My_Image_Copy = My_Image.CopyBlank();

Rectangle Store_ROI = my_image.ROI; //Only need one as both images same size

My_Image.ROI = new Rectangle(50, 50, 100, 100);
My_Image_Copy.ROI = new Rectangle(50, 50, 100, 100);

My_Image_Copy = My_Image.Copy(); //This will only copy the Region Of Interest

//Reset the Regions Of Interest so you will now operate on the whole image 
My_Image.ROI = Store_ROI;
My_Image_Copy.ROI = Store_ROI;

Теперь этоТо же, что и в методе 2, но вам не нужно сортировать циклы записи, где могут возникать ошибки.

Надеюсь, это исправление отвечает на ваш вопрос,

Приветствия

Крис

1 голос
/ 01 апреля 2012
    // Rectangle's parameters
    static int x = 3;
    static int y = 3;
    static int width = 2;
    static int height = 2;

    Rectangle specificArea = new Rectangle(x, y, width, height);

    // Your image matrix; 20x20 just a sample
    Matrix<int> imageMatrix = new Matrix<int>(20, 20);


    public Matrix<int> cropMatrix()
    {
        // Crop a specific area from image matrix
        Matrix<int> specificMatrix = imageMatrix.GetSubRect(specificArea);

        // Matrix with full of zeros and same size with imageMatrix
        Matrix<int> croppedMatrix = imageMatrix.CopyBlank();

        for (int i = x; i < x+width; i++)
        {
            for (int j = y; j < y+height; j++)
            {
                // Set croppedMatrix with saved values
                croppedMatrix[i, j] = specificMatrix[i-x, j-y];
            }
        }

        return croppedMatrix;
    }
...