0

I have some difficulties converting a Mat OpenCV matrix (2D) into a 1D array in OpenCV. I am implementing my code in C++ with Visual Studio and my environment is Windows 10. This is my code

include <opencv2/core/core.hpp>
#include <opencv2/highgui/highgui.hpp>
#include <opencv2/imgproc.hpp>
#include "opencv2/opencv.hpp"
#include <iostream>
#include <vector>

using namespace std;
using namespace cv;

int countt = 1;
int main()
{
    std::cout << "The program starts!\n";
    // Create a VideoCapture object and open the input file
  // If the input is the web camera, pass 0 instead of the video file name
    VideoCapture cap("Control1.avi");

    // Check if camera opened successfully
    if (!cap.isOpened()) {
        cout << "Error opening video stream or file" << endl;
        return -1;
    }
    // Size of the video
    Size capSize = Size((int)cap.get(CAP_PROP_FRAME_WIDTH),
        (int)cap.get(CAP_PROP_FRAME_HEIGHT));
    cout << "Frame Size: " << capSize << endl;
    cout << "Number of Frames: " << cap.get(CAP_PROP_FRAME_COUNT) << endl;

    while (1) {

        Mat frame;
        // Capture frame-by-frame
        cap >> frame;
       
        // If the frame is empty, break immediately
        if (frame.empty())
            break;
        
        //converting Mat frame into 1D array
        int* testData1D = (int*)frame.data;
        cout << "1Darray: " << testData1D[22] << endl;

        // Display the resulting frame
        imshow("Frame", frame);
        cout << "Count = " << countt << endl;
        countt = countt + 1;

        // Press  ESC on keyboard to exit
        char c = (char)waitKey(25);
        if (c == 27)
            break;
    }

    // When everything done, release the video capture object
    cap.release();

    // Closes all the frames
    destroyAllWindows();

    return 0;
}

This code was unsuccessful. I am not able to print a reasonable data from the array. This is a kind of thing I get when I run the code: 1Darray: 134742016. This suppose to be the intensity of a pixel (something between 0 and 255).

I also replaced int* testData1D = (int*)frame.data; with the below code in order to convert the matrix content one by one into the array:

int numCols = frame.cols;
int numRows = frame.rows;
const int frameSize = frame.cols * frame.rows;
double frameArray[201*204];
for (int x = 0; x < numCols; x++) {          // x-axis, cols
    for (int y = 0; y < numRows; y++) {          // y-axis rows
        double intensity = frame.at<uchar>(Point(x, y));
        frameArray[x * frame.cols + y] = intensity;
    }
}

But I end up with an infinite for loop that never ends. (The program runs for ever) I checked bunch of other codes on Stackoverflow such as c++ OpenCV Turn a Mat into a 1 Dimensional Array and Convert Mat to Array/Vector in OpenCV

but they are not helpful. For the latter, the array size is not correct. I don't know if it really build the right array. I get array lenght: 124236, but it should be 204*203 = 41412 I would appreciate it if you show me how I can simply convert a Mat openCV matrix into a normal 1D array in C++.

Thanks.

3
  • 1
    Any reason you are converting the cv:::Mat to an array instead of a vector? To perform the latter operation you can declare a vector like this: std::vector<int> outputVector; and do outputVector.assign( mat.data, mat.data + mat.total()*mat.channels() ); Assuming your mat is an 8-bit type image. Commented Jan 21, 2021 at 2:07
  • 1
    124,236 = 41,412 * 3. I assume your input image is RGB. Commented Jan 21, 2021 at 3:12
  • @eldesgraciado, I want to build this code with arrays and implement it in another program. If you can show me a way to convert Mat to array, I would appreciate it. Commented Jan 21, 2021 at 17:15

1 Answer 1

1

Try looping through the matrix using pointer arithmetic. First, we create a random BGR matrix of size 9, to test the procedure. The data type stored in the mat are BGR pixels represented as cv::Scalars:

//Create random test mat:
cv::Mat3b randomMat(3,3);
cv::randu( randomMat, cv::Scalar(0,0,0), cv::Scalar(256,256,256) );    
cv::Mat testMat = randomMat;

//Get mat total elements:
int matElements = testMat.cols * testMat.rows;

//Prepare output array:
cv::Scalar matArray[ matElements ];

This is the test matrix:

enter image description here

The raw values will be stored in the matArray container. Loop through the matrix using pointer arithmetic and store each pixel in the array:

//Loop trhough the mat, insert into array:
cv::MatIterator_<cv::Vec3b> it, end;
int i = 0;

for ( it = testMat.begin<cv::Vec3b>(), end = testMat.end<cv::Vec3b>(); it != end; ++it ) {

    //get current bgr pixels:
    uchar &r = (*it)[2];
    uchar &g = (*it)[1];
    uchar &b = (*it)[0];

    //Store them into array, as a cv::Scalar:
    matArray[i] = cv::Scalar(b,g,r);
    i++;

}

We can check the data stored in the array like this:

for ( int i = 0; i < matElements; i++ ){
    std::cout<<"i: "<<i<<" - "<<matArray[i]<<std::endl;
}

This yields:

i: 0 - [246, 156, 192, 0]
i: 1 - [7, 165, 166, 0]
i: 2 - [2, 179, 231, 0]
i: 3 - [212, 171, 230, 0]
i: 4 - [93, 138, 123, 0]
i: 5 - [80, 105, 242, 0]
i: 6 - [231, 239, 174, 0]
i: 7 - [174, 176, 191, 0]
i: 8 - [134, 25, 124, 0]
Sign up to request clarification or add additional context in comments.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.