How to copy integer matrix for Mat type in Opencv?

Asked

Viewed 421 times

4

Would you like to know how to copy an integer array to an Opencv Mat type data ? The following is an example I created to illustrate my goal, which corresponds to a given user generated matrix ( ranging from 0 to 255 - color variation in Opencv) to be shown on the screen in color form through the imshow. However what is appearing on the screen is a square all black, IE, the copy is not being well executed since it should appear a band of white color, other black and a third of any color.

That is, I want to convert the integer matrix to the respective matrix type in Opencv (Mat ) and display it correctly through the imshow.

#include <iostream>
#include <string>
#include <opencv2/opencv.hpp>
#include <opencv2/core/core.hpp>
#include <opencv2/highgui/highgui.hpp>
#include <opencv2/imgproc/imgproc.hpp>
#include "opencv2/videoio.hpp"
#include "opencv2/video/tracking.hpp"
#include <stdio.h>
#include <stdlib.h>
#include <math.h>
using namespace std;
using namespace cv;


int main()
{

int image[128][128];
    // Zerando a matriz pra nao pegar lixo da memoria
    for(int i=0; i< 128 ;i++)
    {
        for(int j=0; j<128 ; j++)
        {
            image[i][j]=0;
        }

    }
    // Colorindo a matriz
    for(int i=0; i< 128 ;i++)
    {
        for(int j=0; j<128 ; j++)
        {
            if(i<40){
                image[i][j]=0;
            }
            if(i>40 && i<80){
                image[i][j]=255;
            }
             if(i>80 && i<128){
                image[i][j]=122;
            }
        }

    }
    // Criando matriz para mostrar para o usuario
    Mat Mostrar(128,128, CV_64FC4 );
    // Copiando a matriz original para a outra matriz
    for(int i=0; i< 128 ;i++)
    {
        for(int j=0; j<128 ; j++)
        {
        Mostrar.at<int>(i,j)= image[i][j];
        }

    }
    // Exibindo a matriz em forma de cor para o usuario
    imshow("Exibindo", Mostrar);
    waitKey();
    return 0;
}

EDITED :

Actually (my mistake, I didn’t make it clear ) I’m trying to do this for a color image. Follow the code I’m using :

#include <iostream>
#include <string>
#include <opencv2/opencv.hpp>
#include <opencv2/core/core.hpp>
#include <opencv2/highgui/highgui.hpp>
#include <opencv2/imgproc/imgproc.hpp>
#include "opencv2/videoio.hpp"
#include "opencv2/video/tracking.hpp"
#include <stdio.h>
#include <stdlib.h>
#include <math.h>
using namespace std;
using namespace cv;

int main()
{
  // Abrindo uma imagem colorida
  Mat image = imread("C:\\Users\\imagem.png");

     int m[242][208];

  // Passando a imagem para a  matriz
     for(int i=0; i< 242 ;i++)
    {
        for(int j=0; j<208 ; j++)
        {
          m[i][j]=  (int)image.at<uchar>(i,j);
        }

    }
     for(int i=0; i< 242 ;i++)
    {
        for(int j=0; j<208 ; j++)
        {
        // Aqui farei algo com a imagem, passar algum filtro, etc
        }
    }
// Criando a matriz auxiliar
 Mat Mostrar(242,208,CV_64FC4 );
 for(int i=0; i< 242 ;i++)
 {
        for(int j=0; j<208 ; j++)
        {
            Mostrar.at<int>(i,j)= m[i][j];
        }
        cout << endl;
}


// Exibindo a imagem modificada
    imshow("Exibindo",Mostrar);
    waitKey();

    return 0;

}

This program compiles but does not work the way it should. The way it is there should at least show the original image but I think I’m doing something wrong ( I’m not using the correct number and type of cainais, etc).

I do not know if what I want to do to do this way ai but what I want is to open a color image pass it to an matrix( normal even without being of type Mat) work on these matrix and show the result to the user ( but for this you have to convert to type Mat).

Because my goal is to create the methods that will modify the image manually even, so that you use as little as possible Opencv.

EDITED 2 :

Now it’s pretty much the way I want it but it’s showing 2 errors :

In the code below I’m taking the image and extracting each channel of it and storing it in an array to later work on these channels. However the way this code( only to show that the conversion worked because both images must be the same) the modified output ( Show ) is showing some black columns at the end of the image, that is, the last columns of this matrix are not equal to the original matrix, but I do not know what may be.

The second problem is if I break down the line :

 //   r[i][j] =30 ;

The code compiles but the execution error ( locks everything ) what theoretically was not to give because I should modify the value if I want.

Is there any way to fix these two mistakes ? Don’t modify this code too much because I want these parts well defined even as it is( because my goal is to separate into functions , one to generate the matrices, others to modify them and one to show the result).

Follows the code :

#include <iostream>
#include <string>
#include <opencv2/opencv.hpp>
#include <opencv2/core/core.hpp>
#include <opencv2/highgui/highgui.hpp>
#include <opencv2/imgproc/imgproc.hpp>
#include "opencv2/videoio.hpp"
#include "opencv2/video/tracking.hpp"
#include <stdio.h>
#include <stdlib.h>
#include <math.h>
using namespace std;
using namespace cv;

int main()
{

     Mat image = imread("C:\\Users\\imagem.png");
     int r[image.rows][image.cols],g[image.rows][image.cols],b[image.rows][image.cols];
     Vec3b  color = image.at<Vec3b>(Point(0,0)); // para inicializar

    // pegando cada canal de cor
     for(int i=0; i< image.rows ;i++)
     {
        for(int j=0; j<image.cols ; j++)
        {
          color = image.at<Vec3b>(Point(i,j));
          r[i][j]=  color[0];
          g[i][j]=  color[1];
          b[i][j]=  color[2];
        }

     }

     Mat Mostrar(image.rows,image.cols,image.type());

    // aqui seria para modificar os canais
    for(int i=0; i< image.rows ;i++)
    {
        for(int j=0; j<image.cols ; j++)
        {
         //   r[i][j] =30 ;
        }

    }


    // Juntando novamente para poder mostrar
     for(int i=0; i< image.rows ;i++)
    {
        for(int j=0; j<image.cols ; j++)
        {
           color[0] = r[i][j];
           color[1] = g[i][j];
           color[2] = b[i][j];
           Mostrar.at<Vec3b>(Point(i,j)) = color;
        }

    }


    imshow("Exibe original",image);
    imshow("Exibe modificada",Mostrar);
    waitKey();

    return 0;

}

1 answer

2

Hello, the point is that you are trying to render a grayscale image so the data type for the matrix is not CV_64FC4, but CV_8UC1 (8 bits without signal and 1 channel only).

#include <iostream>
#include <string>
#include <opencv2/opencv.hpp>
#include <opencv2/core/core.hpp>
#include <opencv2/highgui/highgui.hpp>
#include <opencv2/imgproc/imgproc.hpp>
#include "opencv2/videoio.hpp"
#include "opencv2/video/tracking.hpp"
#include <stdio.h>
#include <stdlib.h>
#include <math.h>

using namespace std;
using namespace cv;

int main() {

    int image[128][128];

    // Colorindo a matriz
    for(int i = 0; i < 128; i++)
        for(int j = 0; j < 128; j++) {
            if(i < 40)
                image[i][j] = 0;
            if(i > 40 && i < 80)
                image[i][j] = 255;
            if(i > 80 && i < 128)
                image[i][j] = 122;
        }

    // Criando matriz para mostrar para o usuario
    Mat Mostrar(128, 128, CV_8UC1);

    // Copiando a matriz original para a nova matriz
    for(int i = 0; i < 128; i++)
        for(int j = 0; j < 128; j++)
            Mostrar.at<uchar>(i, j) = image[i][j]; // Veja: <uchar>!

    // Exibindo a matriz em forma de cor para o usuario 
    imshow("Exibindo", Mostrar);
    waitKey();
    return 0;
}

This will display almost a flag of Estonia to the user.


Answer 2, after request for color image

In this case where you will already load a ready image, it makes no sense to have the matrices m and Mostrar, discard them. The object itself imagem is the only thing you need. You can browse it and edit it directly.

But as now the image is colored, and the colors have 3 channels (Red, Green, Blue, or 4 channels if you count the Alpha), you may need the class Vec3b to help store the values, otherwise you can access directly as in this example: image.at<Vec3b>(Point(x, y))[2] = 255.

#include <iostream>
#include <string>
#include <opencv2/opencv.hpp>
#include <opencv2/core/core.hpp>
#include <opencv2/highgui/highgui.hpp>
#include <opencv2/imgproc/imgproc.hpp>
#include "opencv2/videoio.hpp"
#include "opencv2/video/tracking.hpp"
#include <stdio.h>
#include <stdlib.h>
#include <math.h>

using namespace std;
using namespace cv;

int main(int argc, const char** argv) {
    // Lendo uma imagem colorida via parâmetro
    Mat image = imread(argv[1]);
    // Poderia ser assim também
    // Mat image = imread("C:\\Users\\imagem.png");

    for(int y = 0; y < image.rows; y++)
      for(int x = 0; x < image.cols; x++) {
          // Obtém o valor do pixel
          Vec3b & color = image.at<Vec3b>(Point(x,y));

          // Faz algo com o pixel...
          // AMARELANDO A IMAGEM PIXEL A PIXEL
          color[0] = 30;
          // color[1] = ?;
          // color[2] = ?;  
       }

    // Exibindo a imagem modificada
    imshow("Exibindo", image);
    waitKey();

    return 0;
}

If you need to always keep the original image as a reference, just copy or reload to another variable: Mat img_original = imread(argv[1]);.

  • Hello friend, your answer is almost what I want even. However I wanted to make it to color image. PS : I edited the question for further clarification.

  • Please check if you answer after answer 2.

  • Hello, your answer 2 helped a lot. But it is still presenting 2 errors, which perhaps are nonsense that I am not realizing, please see the edited question ( EDITED 2 ).

  • I didn’t find the errors you report in your last code (copied and paste directly into the compiler). I obtained as a result the display of the two images, an original, another yellowish (I discolored r[i][j] = 30;). I have nothing more I can add now.

  • 1

    Hey, buddy, I got the problem solved. However, because you have answered the question and solved virtually all doubts I assign the reward you.

Browser other questions tagged

You are not signed in. Login or sign up in order to post.