Work with matrix in emgu cv

前端 未结 2 1702
后悔当初
后悔当初 2021-01-26 19:22

I have a matrix (2D) of an image in EMGU cv,how can I fill the rest of the matrix with zeros but keep a certain area(rectangle) with the original data?

相关标签:
2条回答
  • 2021-01-26 19:43
        // 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;
        }
    
    0 讨论(0)
  • 2021-01-26 19:48

    Method 1

    One way to achieve what your after is to access the Data of the Matrix directly and set the values to '0' the following code will set the lower quarter of 'My_Matrix' to 0 where all other values will remain 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; 
        }
    }
    

    To achieve what you wanted from your comment you must still take the same approach My_Matrix_Image would contain your image data values from 0-255 I will give solutions for both greyscale and colour images. I will keep the first 30 rows of the image and set the rest to zero the image will be 100x100 pixels in size. Change j = 30 to alter the amount of rows.

    First Colour Image Matrix there will be 3 channels Red, Green and Blue:

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

    Greyscale Image Matrices are easier as there will be 1 channel:

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

    Now lets assume you want to keep the Middle 40 Rows you will have to add an additional loop remember this is the only way with a Matrix I have only provided the colour image example as you can see it starts getting a little messy and Method 2 may be better:

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

    Method 2

    Now lets assume you do want to keep a rectangle of data. Creating 6 Loops is complex and inefficient so here is what you could do.

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

    The above code will copy the centre 20x20 pixels from an image you can obviously change this to copy whole rows by using for(int i = 0; i< My_Matrix_Image.Height; i++)

    Much better I'm sure you will agree.

    Alternative

    Now while you are using a Matrix to store you data using a Image construct makes coding a little simpler. While this may not be relevant to you it may be to others.

    If you use Image or alternative to store your Image data then this can be achieved by:

    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;
    

    Now this the same as Method 2 but you don't need to sort write out loops where errors can occur.

    Hope this correction answers your question,

    Cheers

    Chris

    0 讨论(0)
提交回复
热议问题