How to copy array of integers to type Mat in OpenCV?

4

I would like to know how to copy an array of integers to an OpenCV Mat-type data? The following is an example I created to illustrate my goal, which corresponds to a given user-generated array (ranging from 0 to 255 - color variation in OpenCV) to be displayed on the screen as a color through imshow . However, what is appearing on the screen is a black square, that is, the copy is not being executed well since it should appear a strip of white color, another one of black color and a third one of any color.

That is, I want to convert the array of integers to their array type in OpenCV (Mat) and display it correctly through 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;
}

EDIT:

In reality (my mistake, I did not make it clear) I'm trying to do this for a color image myself. Here is 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's 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 cords, etc.).

I do not know if what I want to do is to do it that way, but what I want is to open a colored image and move it to an array (normal even if it is not of the type Mat) to work on those arrays 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, so that the OpenCV is used as little as possible.

EDIT 2:

Now it's pretty much the way I want it, but it has 2 errors:

In the code below I'm taking the picture and extracting each channel from it and saving it in an array to later work on those channels. However the way the code is (just to show that the conversion worked out because both images must be the same) the modified output (Show) is displaying some black columns at the end of the image, ie the last columns of this matrix do not are the same as the original array, but I do not know what it might be.

The second problem is if I uncomment the line:

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

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

Is there any way to fix these two errors? Without modifying this code a lot because I want these parts well defined the way it is (because my goal is to separate in functions, one to generate the matrices, others to modify them and one to show the result).

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

}
    
asked by anonymous 20.07.2017 / 15:00

1 answer

2

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

#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 almost display a flag from Estonia to the user.

Response 2 after request for color image

In this case where you are loading a ready-made image, it does not make sense to have the arrays m and Mostrar , discard them. The imagem object itself is the only thing you need. You can browse and edit it directly.

But since now the image is colored, and the colors have 3 channels ( Red , Green , Blue ), or 4 Alpha ), you may need the class Vec3b to help store the values, otherwise you can access direct 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, simply copy or reload it to another variable: Mat img_original = imread(argv[1]); .

    
26.07.2017 / 03:41