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
Стоит ли изучать PHP в 2026-2027 годах?
Стоит ли изучать PHP в 2026-2027 годах?
Привет всем, сегодня я хочу высказать свои соображения по поводу вопроса, который я уже много раз получал в своем сообществе: "Стоит ли изучать PHP в...
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
В JavaScript одним из самых запутанных понятий является поведение ключевого слова "this" в стрелочной и обычной функциях.
Приемы CSS-макетирования - floats и Flexbox
Приемы CSS-макетирования - floats и Flexbox
Здравствуйте, друзья-студенты! Готовы совершенствовать свои навыки веб-дизайна? Сегодня в нашем путешествии мы рассмотрим приемы CSS-верстки - в...
Тестирование функциональных ngrx-эффектов в Angular 16 с помощью Jest
В системе управления состояниями ngrx, совместимой с Angular 16, появились функциональные эффекты. Это здорово и делает код определенно легче для...
Концепция локализации и ее применение в приложениях React ⚡️
Концепция локализации и ее применение в приложениях React ⚡️
Локализация - это процесс адаптации приложения к различным языкам и культурным требованиям. Это позволяет пользователям получить опыт, соответствующий...
Пользовательский скаляр GraphQL
Пользовательский скаляр GraphQL
Листовые узлы системы типов GraphQL называются скалярами. Достигнув скалярного типа, невозможно спуститься дальше по иерархии типов. Скалярный тип...
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;
    }
  }
}

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