Philippine Prevost
Philippine Prevost

Reputation: 21

C++/OpenCV Can't initialize 3D Mat

I have a problem with initializing a 3D Mat with openCV. I would like to create a 3D matrix of size (rows x cols x 16), rows and cols being the dimensions of an image given earlier in the program. I tried I can not say how many different methods, and all return to me more or less the same thing: the dimensions of my matrices are worth 0 or -858993460.

My code lines :

Mat image_Conv;

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

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

Can you tell me why I have this problem? Of course I read all the posts that speak, read the doc opencv on the class Mat, but nothing works, I still have the same problem. I specify that my data in the Mat will be float.

The code :

// 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 : Most of the code is not mine, I have to use it for my internship and can only edit between the lines :

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

and

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

Thank you for your help !

EDIT : My first problem is solved, but it seems that it didn't work after all. I suppose that Mat::zeros set all the Mat elements at 0, right ? But if I write

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

I have the error : "Unhandled exception at 0x000007FEFD4FA06D in xxxxxx.exe: Microsoft C++ exception: cv::Exception at memory location 0x000000000023E540.".

I don't know what the problem is with the memory and how to fix it.

My goal is to fill my matrix element by element thanks to several for loops which will be realized several operations, before the result is written in the element of my corresponding Mat. I did that why 3D and 4D arrays, and maybe it's the easiest solution, to do all the calculs with arrays, but I can't go from a 3D array to a 3D Mat or a 3D Mat to a 3D array.

Upvotes: 0

Views: 2327

Answers (2)

Catree
Catree

Reputation: 2517

You should be able to create a multi-dimensional matrix filled with 0-values using:

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

You can iterate over the matrix with M.at(i,j,k) (only for 3D matrix created as above):

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

Alternatively, you should be able to create a 2D matrix with multiple channels with:

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

To iterate over the 2D matrix and over the channels:

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

Upvotes: 1

Arkady Godlin
Arkady Godlin

Reputation: 588

just tested this on visual studio 2015, opencv 3.4

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

this works fine.

Upvotes: 1

Related Questions