【问题标题】:C++/OpenCV Can't initialize 3D MatC++/OpenCV 无法初始化 3D Mat
【发布时间】:2018-09-21 03:36:15
【问题描述】:

我在使用 openCV 初始化 3D Mat 时遇到问题。 我想创建一个大小为(行 x 列 x 16)的 3D 矩阵,行和列是程序前面给出的图像的尺寸。我试过了我不能说有多少不同的方法,而且都或多或少地返回给我同样的东西:我的矩阵的维度值是 0 或 -858993460。

我的代码行:

Mat image_Conv;

int rows = imageBicubic.rows;
int cols = imageBicubic.cols;

image_Conv = Mat::zeros(rows, cols, CV_32FC(16));

你能告诉我为什么我有这个问题吗?当然,我阅读了所有会说话的帖子,阅读了 Mat 类上的 doc opencv,但没有任何效果,我仍然遇到同样的问题。我指定我在 Mat 中的数据是浮动的。

代码:

// Include standard headers
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <vector>
#include <ctime>

#include <iostream>
using namespace std;

//#include <opencv.hpp>
#include <opencv/cv.h>
#include <opencv2/core/core.hpp>
#include <opencv2/imgproc/imgproc.hpp>
#include <opencv2/imgcodecs.hpp>
#include <opencv/highgui.h>
using namespace cv;

////////////////////////////////////////
// main file
int main() 
{
    string fileName = "myImage.jpg";

    Mat imageSrc = cv::imread(fileName, CV_LOAD_IMAGE_UNCHANGED);   // Read the file
    if (!imageSrc.data) // Check for invalid input
    {
        cout << "Could not open or find the image\n";
        return 1;
    }
    cout << "Loaded " << fileName << " (" << imageSrc.channels() << " channels)\n";

    //int colorTransform = (imageSrc.channels() == 4) ? CV_BGRA2RGBA : (imageSrc.channels() == 3) ? CV_BGR2RGB : CV_GRAY2RGB;
    //cv::cvtColor(imageSrc, imageSrc, colorTransform);

    imageSrc.convertTo(imageSrc, CV_32F, 1 / 255.0, 0.0);

    int SliceSizeWidth = imageSrc.cols / 2;
    int sliceShiftWidth = imageSrc.cols / 4;
    int sliceWidthNumber = (imageSrc.cols / sliceShiftWidth) - 1;

    int SliceSizeHeight = imageSrc.rows / 2;
    int sliceShiftHeight = imageSrc.rows / 4;
    int sliceHeightNumber = (imageSrc.rows / sliceShiftHeight) - 1;

    for (int sliceIndexHeight = 0; sliceIndexHeight < sliceHeightNumber; sliceIndexHeight++)
    {
        for (int sliceIndexWidth = 0; sliceIndexWidth < sliceWidthNumber; sliceIndexWidth++)
        {
            Mat patchImage = imageSrc(Rect(sliceIndexWidth*sliceShiftWidth, sliceIndexHeight*sliceShiftHeight, SliceSizeWidth, SliceSizeHeight));

            Mat patchImageCopy;
            patchImage.copyTo(patchImageCopy); // Deep copy => data are contiguous in patchImageCopy

            Mat imageBicubic;

            resize(patchImageCopy, imageBicubic, Size(2 * patchImage.cols, 2 * patchImage.rows), INTER_CUBIC);


            Mat image_Padding;
            int padding = 1;

            copyMakeBorder(imageBicubic, image_Padding, padding, padding, padding, padding, BORDER_CONSTANT, Scalar(0));


            Mat image_Conv;

            int rows = imageBicubic.rows;
            int cols = imageBicubic.cols;

            image_Conv = Mat::zeros(rows, cols, CV_32FC(16));

            /* rest of the code I have to write */


            image_Conv.convertTo(image_Conv, CV_8U, 255.0, 0.0);

            string nameBase = fileName.substr(0, fileName.find('.'));
            string nameExt = fileName.substr(fileName.find('.'), fileName.length() - nameBase.length());

            string strH = to_string(sliceIndexHeight);
            string strW = to_string(sliceIndexWidth);

            string outFileName = nameBase + "_H" + strH + "W" + strW + nameExt;

            imwrite(outFileName, image_Conv);

        }
    }
    return 0;
}

PS : 大部分代码不是我的,我实习用的,只能在字里行间编辑:

resize(patchImageCopy, imageBicubic, Size(2 * patchImage.cols, 2 * patchImage.rows), INTER_CUBIC);

image_Conv.convertTo(image_Conv, CV_8U, 255.0, 0.0);

感谢您的帮助!

编辑:我的第一个问题解决了,但似乎它毕竟没有工作。我想 Mat::zeros 将所有 Mat 元素设置为 0,对吗?但是如果我写

cout << image_Conv.at<float>(0,0,0) << endl; 

我遇到错误:“xxxxxx.exe 中 0x000007FEFD4FA06D 处的未处理异常:Microsoft C++ 异常:内存位置 0x000000000023E540 处的 cv::Exception。”。

我不知道内存有什么问题以及如何修复它。

我的目标是通过几个 for 循环逐个元素地填充我的矩阵元素,这将实现几个操作,然后将结果写入我相应 Mat 的元素中。我这样做了,为什么 3D 和 4D 数组,也许这是最简单的解决方案,用数组进行所有计算,但我不能从 3D 数组到 3D Mat 或 3D Mat 到 3D 数组。

【问题讨论】:

  • OP 你应该提供一些错误信息的例子
  • 我刚刚编辑了带有错误消息的帖子。感谢您的宝贵时间!

标签: c++ opencv


【解决方案1】:

刚刚在 Visual Studio 2015,opencv 3.4 上测试过这个

cv::Mat mat = cv::Mat::zeros(5, 5, CV_32FC(16));

这很好用。

【讨论】:

  • @GPPK 你是对的,我之前不知道,只是测试了它并编辑了我的答案。
  • 现在它可以工作了,我真的不知道为什么......我用 5 更改行和列,然后通过行和列更改 5,它可以工作。感谢您的宝贵时间!
  • 哼,好像还是不行。我想 Mat::zeros 将所有 Mat 元素设置为 0,对吗?但是如果我写 cout (0,0,0)
  • float* t = &(mat.at(cv::Point(0, 0))); *t = 1; *(t+1) = 1;您可以使用此代码设置前 2 个通道中的值。不知道另一种方法来做到这一点
  • 我不知道如何使用它。如果我希望通道 0 的 Point(0,0) 为 1,通道 1 的 Point(0,0) 为 17,我是否必须写 *t = 1; *(t+1) = 17; ?
【解决方案2】:

您应该能够使用以下方法创建一个填充 0 值的 multi-dimensional matrix

int size[3] = { 5, 4, 3 };
cv::Mat M(3, size, CV_32F, cv::Scalar(0));

您可以使用M.at(i,j,k) 迭代矩阵(仅适用于如上创建的 3D 矩阵):

for (int i = 0; i < size[0]; i++) {
  for (int j = 0; j < size[1]; j++) {
    for (int k = 0; k < size[2]; k++) {
      M.at<float>(i,j,k) = i*12+j*3+k;
    }
  }
}

for (int i = 0; i < size[0]; i++) {
  for (int j = 0; j < size[1]; j++) {
    for (int k = 0; k < size[2]; k++) {
      std::cout << "M(" << i << ", " << j << ", " << k << "): " << M.at<float>(i,j,k) << std::endl;
    }
  }
}

或者,您应该能够创建一个具有多个通道的二维矩阵

cv::Mat M(5, 4, CV_32FC(3), cv::Scalar(0));

迭代二维矩阵和通道:

for (int i = 0; i < M.rows; i++) {
  for (int j = 0; j < M.cols; j++) {
    for (int k = 0; k < M.channels(); k++) {
      M.at<cv::Vec<float, 3> >(i,j)[k] = i*M.cols*M.channels()+j*M.channels()+k;
    }
  }
}

【讨论】:

    猜你喜欢
    • 2023-03-30
    • 2019-04-28
    • 1970-01-01
    • 2020-09-24
    • 1970-01-01
    • 2013-05-10
    • 2019-08-28
    • 2017-08-28
    • 1970-01-01
    相关资源
    最近更新 更多