0

I'm getting segmentation fault while trying to access indexes of a 3D CV::Mat. The code is following,

int channel = 3;
int sizes[] = { imageheight, imageWidth};
CV::Mat test(2, sizes, CV_8UC3)
for(int i=0;i<image2D->size();i++)
    {
        Point2D &_point = image2D->at(i);       

        test.at<unsigned char>(_point.y,_point.x,0) = _point.rgb.r;
        test.at<unsigned char>(_point.y,_point.x,1) = _point.rgb.g;
        test.at<unsigned char>(_point.y,_point.x,2) = _point.rgb.b; // Segmentation fault in this line
    }

The following way doesn't crash but it outputs a black image. I'm not sure if I'm doing it correctly,

unsigned char *ptest = test.ptr<unsigned char>(_point.y);
        ptest[channel*_point.x+ 0] = _point.rgb.r;
        ptest[channel*_point.x+ 1] = _point.rgb.g;
        ptest[channel*_point.x+ 2] = _point.rgb.b;

EDIT:

Updated the code to the following gives me compile error invalid types ‘unsigned char[int]’ for array subscript,

Matrix test(imageheight, imageWidth, CV_8UC3);
for(int i=0;i<image2D->size();i++)
    {
        Point2D &_point = image2D->at(i);
        // Compile error on the below 3 lines.
        test.at<unsigned char>(_point.y, _point.x)[0] = _point.rgb.b;
        test.at<unsigned char>(_point.y, _point.x)[1] = _point.rgb.g;
        test.at<unsigned char>(_point.y, _point.x)[2] = _point.rgb.r;

    }

Compile error is in the position where I access the channel index with []. I guess this is not the right way to access channels.

Tahlil
  • 2,680
  • 6
  • 43
  • 84
  • The first argument of the matrix constructor should be number of channels, it should be 3 not 2. Also you should probably be using the Mat class, not Matrix. – alkasm Oct 13 '17 at 21:09
  • I have edited the question. The matrix is typedef of cv::Mat. I thought first argument would be the size of the `sizes` array? – Tahlil Oct 13 '17 at 21:11
  • Check the [docs](https://docs.opencv.org/3.1.0/d3/d63/classcv_1_1Mat.html). First argument should be the number of dimensions. Edit: just realized I said number of channels in the first comment, meant dimensions. Your sizes array should thus also contain the number of channels for the third dim. – alkasm Oct 13 '17 at 21:13

1 Answers1

1

The easiest way to access cv::Mat with multiple channels,

cv::Mat3b test(imageheight, imageWidth, CV_8UC3);
for(int i=0;i<image2D->size();i++)
{
    Point2D &_point = image2D->at(i);
    test.at<cv::Vec3b>(_point.y, _point.x)[0] = _point.rgb.b;
    test.at<cv::Vec3b>(_point.y, _point.x)[1] = _point.rgb.g;
    test.at<cv::Vec3b>(_point.y, _point.x)[2] = _point.rgb.r;
}

For a single channel cv::Mat

cv::Mat test(imageheight, imageWidth, CV_32FC1);

for(int i=0;i<image2D->size();i++)
{
    Point2D &_point = image2D->at(i);
    test.at<float>(_point.y, _point.x) = _point.r;
}

Thanks to this answer.

Tahlil
  • 2,680
  • 6
  • 43
  • 84