如何在 C++ 中将 OpenCV 2D 矩阵转换为 1D 数组?

Posted

技术标签:

【中文标题】如何在 C++ 中将 OpenCV 2D 矩阵转换为 1D 数组?【英文标题】:How to convert a OpenCV 2D matrix into a 1D array in C++? 【发布时间】:2021-01-21 01:51:56 【问题描述】:

我在 OpenCV 中将 Mat OpenCV 矩阵 (2D) 转换为 1D 数组时遇到了一些困难。我正在使用 Visual Studio 在 C++ 中实现我的代码,我的环境是 Windows 10。 这是我的代码

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;

此代码不成功。我无法从数组中打印出合理的数据。这是我在运行代码时得到的一种东西:1Darray: 134742016。这假设是像素的强度(介于 0 和 255 之间)。

我还用下面的代码替换了int* testData1D = (int*)frame.data;,以便将矩阵内容一一转换成数组:

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;
    

但我最终得到了一个永远不会结束的无限 for 循环。 (程序永远运行) 我在 *** 上检查了一堆其他代码,例如 c++ OpenCV Turn a Mat into a 1 Dimensional Array 和 Convert Mat to Array/Vector in OpenCV

但它们没有帮助。对于后者,数组大小不正确。我不知道它是否真的构建了正确的数组。我得到数组长度:124236,但它应该是 204*203 = 41412 如果您向我展示如何简单地将 Mat openCV 矩阵转换为 C++ 中的普通一维数组,我将不胜感激。

谢谢。

【问题讨论】:

您有什么理由将cv:::Mat to 转换为array 而不是vector?要执行后面的操作,您可以像这样声明一个向量:std::vector&lt;int&gt; outputVector; 并执行 outputVector.assign( mat.data, mat.data + mat.total()*mat.channels() ); 假设您的 mat 是一个 8 位类型的图像。 124,236 = 41,412 * 3。我假设您的输入图像是 RGB。 @eldesgraciado,我想用数组构建这段代码并在另一个程序中实现它。如果您能告诉我一种将 Mat 转换为数组的方法,我将不胜感激。 【参考方案1】:

尝试使用指针算法循环遍历矩阵。首先,我们创建一个大小为9 的随机BGR 矩阵来测试该过程。 mat中存储的数据类型为BGR像素,表示为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 ];

这是测试矩阵:

原始值将存储在matArray 容器中。使用指针算法循环遍历矩阵并将每个像素存储在数组中:

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


我们可以像这样检查存储在数组中的数据:

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

这会产生:

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]

【讨论】:

以上是关于如何在 C++ 中将 OpenCV 2D 矩阵转换为 1D 数组?的主要内容,如果未能解决你的问题,请参考以下文章

如何使用 C# 脚本在 Unity 中将 OpenCV Mat 转换为 Texture2D?

使用 OpenCV 在 C++ 中将 std::list 转换为 cv::Mat

如何将 C++ 数组转换为 opencv Mat

如何在 C++ 中将 TF_Tensor 转换为 opencv Mat?

opencv4opencv视频教程 C++(opencv教程)3矩阵的掩膜操作(filter2D)

如何在 C++ 中将一组整数转换为 3D 向量?