在emgu cv中使用矩阵

时间:2011-08-25 21:04:14

标签: c# matrix emgucv

我在EMGU cv中有一个图像的矩阵(2D),如何用零填充矩阵的其余部分,但保留一个区域(矩形)和原始数据?

2 个答案:

答案 0 :(得分:3)

方法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行你必须添加一个额外的循环记住这是使用矩阵的唯一方法我只提供了彩色图像示例,你可以看到它开始变得有点凌乱,方法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像素,您可以通过使用 for(int i = 0; i&lt; My_Matrix_Image.Height; i ++)显然更改此内容以复制整行)

好多了,我相信你会同意的。

<强>替代

现在,当您使用Matrix来存储使用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 :(得分:1)

    // 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;
    }