Kevin Katzke
Kevin Katzke

Reputation: 3771

Compute 3D gradient directions in OpenCV

I have a 160x120 OpenCV Mat in which I have stored a Vec3F vector at each position. The Vec3f holds (x, y, z) information for a specific pixel that has been computed through 3D reconstruction using a intensity image and a corresponding depthmap. So I basically map from a Mat holding a greyscale value at each pixel to a Mat holding 3D position information at each pixel.

Then I tried to compute the gradients for each pixel in that Mat object. I therefore have implemented this code in C++/OpenCV:

for(int x = 0; x < mat.rows; ++x){
    for(int y = 0; y < mat.cols; ++y){
        float Gx = (mat.at<Vec3f>(x+1, y)[0] - mat.at<Vec3f>(x-1, y)[0]) / 2.0;
        float Gy = (depth.at<Vec3f>(x, y+1)[1] - depth.at<Vec3f>(x, y-1)[1]) / 2.0;

        Vec3f d = (Gx, Gy, 1.0);
        Vec3f n = normalize(d);
        allGradients.push_back(n);
    }
}

// mat.at<Vec3f>(x, y)[0] -> Get the Vec3F vector at the current x-, y- 
// position in the Mat and access its first element (which is the points x-value). 

So I computed the gradient directions Gx and Gy with the method of finite difference approximation.

What I don't understand is how to compute the gradient in the z-direction. I do have the z-information for every pixel stored in the Vec3f along with the x-, and y-information but the step of finite difference approximation wont be possible, as the data is stored in a 2D Mat, right?

So I cannot simply access the pixel in front and behind he current one by doing something similar like this:

 float Gz = (mat.at<Vec3f>(x, y, z+1)[2] - mat.at<Vec3f>(x, y, z-1)[2]) / 2.0;

as in a Mat I have not z-value, right? If so, how can I then compute the gradient in the z-direction? Would I need to store my information in a 3D array? Or is the whole approach incorrect? Thanks!

Upvotes: 0

Views: 749

Answers (1)

Pankaj Daga
Pankaj Daga

Reputation: 761

It seems like what you have is a 3-dimensional object which you have somehow coerced into a 2D matrix. If you truly have a 3D volumetric object, you can use the following Opencv Mat constructor

Mat::Mat(int ndims, const int* sizes, int type)

See the documentation here: http://docs.opencv.org/2.4/modules/core/doc/basic_structures.html#mat-mat

This constructor allows you to create n-dimensional Mat objects. Example:

cv::Mat m = cv::Mat(3, {100, 100, 10}, CV_32SC1)

If your input is a 2-dimensional spatial object with some 3-dimensional field attached at every pixel, then of course, the spatial gradient along the z-direction is 0 but I am guessing your input is a full volumetric object?

Upvotes: 1

Related Questions