C++ / opencv не может инициализировать 3d mat

У меня проблема с инициализацией 3D-мата с помощью openCV. Я хотел бы создать трехмерную матрицу размера (строки x столбцы x 16), где строки и столбцы являются размерами изображения, указанного ранее в программе. Я пробовал не могу сказать, сколько разных методов, и все возвращают мне более или менее одно и то же: размеры моих матриц стоят 0 или -858993460.

Мои строки кода:

Mat image_Conv;

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

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

Подскажите, почему у меня такая проблема? Конечно, я прочитал все сообщения, которые говорят, прочитал 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; 

У меня ошибка: «Необработанное исключение по адресу 0x000007FEFD4FA06D в xxxxxx.exe: исключение Microsoft C++: cv :: Exception в ячейке памяти 0x000000000023E540.».

Не знаю, в чем проблема с памятью и как ее исправить.

Моя цель состоит в том, чтобы заполнить мою матрицу элемент за элементом благодаря нескольким циклам for, которые будут реализованы за несколько операций, прежде чем результат будет записан в элемент моего соответствующего Mat. Я сделал это, почему массивы 3D и 4D, и, возможно, это самое простое решение, выполнять все вычисления с массивами, но я не могу перейти от 3D-массива к 3D-мату или 3D-мату к 3D-массиву.

OP вы должны предоставить несколько примеров сообщений об ошибках

GPPK 11.04.2018 12:32

Я только что отредактировал сообщение со своим сообщением об ошибке. Спасибо за ваше время !

Philippine Prevost 11.04.2018 17:00
0
2
1 161
2

Ответы 2

только что протестировал это в Visual Studio 2015, opencv 3.4

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

это отлично работает.

@GPPK, вы правы, я не знал об этом раньше, просто протестировал и отредактировал свой ответ.

Arkady Godlin 11.04.2018 12:07

Теперь это работает, я действительно не знаю почему ... Я меняю строки и столбцы на 5, затем меняю 5 на строки и столбцы, и это работает. Спасибо за ваше время !

Philippine Prevost 11.04.2018 13:10

Хм, кажется, все-таки не сработало. Я полагаю, что Mat :: zeros устанавливает все элементы Mat в 0, верно? Но если я напишу cout << image_Conv.at <float> (0,0,0) << endl; У меня ошибка: «Необработанное исключение по адресу 0x000007FEFD4FA06D в xxxxxx.exe: исключение Microsoft C++: cv :: Exception в ячейке памяти 0x000000000023E540.». Не знаю в чем проблема с памятью и как исправить

Philippine Prevost 11.04.2018 15:48

float * t = & (mat.at <float> (cv :: Point (0, 0))); * t = 1; * (t + 1) = 1; вы можете использовать этот код для установки значений в первых 2 каналах. не знаю другого способа сделать это

Arkady Godlin 11.04.2018 16:07

Я не знаю, как этим пользоваться. Если я хочу, чтобы точка (0,0) канала 0 находилась в 1, а точка (0,0) канала 1 - в 17, нужно ли мне писать * t = 1; * (t + 1) = 17; ?

Philippine Prevost 11.04.2018 17:13

да для (int я = 0; я <16; я ++) * (т + я) = я;

Arkady Godlin 11.04.2018 17:14

Снова та же ошибка ... У меня t = 0x0000000000000000 и «<Невозможно прочитать память>»

Philippine Prevost 12.04.2018 10:23

Вы должны иметь возможность создать многомерная матрица, заполненный нулевыми значениями, используя:

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

В качестве альтернативы вы можете создать 2D-матрица с несколькими каналами с помощью:

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

Чтобы перебрать 2D-матрицу и каналы:

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

Другие вопросы по теме