2015-09-23 4 views
0

Я хочу изменить часть многомерной матрицы, используя openCV. В основном я хочу, чтобы достичь того же, как написано в Matlab:Как изменить часть многомерной матрицы в openCV?

A = zeros(5,5,25); 
A(:,:,1) = some_matrix1; 
A(:,:,2) = some_matrix2; 

Я не уверен, если я должен использовать матрицу 5x5 с 25 каналами или 5x5x25 матрицы с одним каналом. Вот что я пробовал:

int dim[3] = { 5,5,25 }; 
Mat A(3, dim, CV_32FC(1), Scalar::all(0)); 
A(Range::all(),Range::all(),0) = some_matrix; 

Но, похоже, я могу использовать только Range для двух измерений. Или

Mat A(5, 5, CV_32FC(25), Scalar::all(0)); 
A(Range::all(),Range::all())[0] = some_matrix; 

Но в данном случае я не знаю, как получить доступ к каналу. Не могли бы вы помочь мне?

+0

здесь смотрите http://docs.opencv.org/modules/core/doc/basic_structures.html?#NAryMatIterator – bendervader

ответ

1

OpenCV оптимизирован для 2D-матриц. Многомерная матрица будет работать, но довольно неэффективна и труднодоступна.

Этот пример кода покажет вам, как писать и читать значения из 3D-матрицы:

#include <opencv2\opencv.hpp> 
using namespace cv; 

int main() 
{ 
    int sizes[] = { 5, 5, 25 }; 
    Mat data(3, sizes, CV_32F); 

    Mat1f some_matrix(sizes[0], sizes[1]); 
    randu(some_matrix, 0.f, 100.f); // some random values 

    // Init data with each plane a constant increasing value 
    for (int z = 0; z < data.size[2]; ++z) 
    { 
     // Set each z-plane to some scalar value 
     Range ranges[] = { Range::all(), Range::all(), Range(z, z + 1) }; 
     data(ranges) = data.size[2] - z; 
    } 

    // Set the n-th z-plane to some_matrix 
    int z = 0; 
    for (int r = 0; r < sizes[0]; ++r) 
    { 
     for (int c = 0; c < sizes[1]; ++c) 
     { 
      data.at<float>(r, c, z) = some_matrix(r, c); 
     } 
    } 

    // Access all slices along z dimension 
    for (int z = 0; z < data.size[2]; ++z) 
    { 
     Range ranges[] = { Range::all(), Range::all(), Range(z, z + 1) }; 
     Mat slice3d(data(ranges).clone()); // with clone slice is continuous, but still 3d 
     Mat slice(2, &data.size[0], data.type(), slice3d.data); 
    } 

    return 0; 
} 

Однако, это намного проще и практичнее хранить 5x5x25 3D матрицу как std::vector<Mat>, где vector имеет длину 25, и каждая матрица представляет собой 2D 5x5.

Смотрите код:

#include <opencv2\opencv.hpp> 
using namespace cv; 

int main() 
{ 
    int sizes[] = { 5, 5, 25 }; 

    vector<Mat> data(sizes[2]); 
    // Init data with each plane a constant increasing value 
    for (int z = 0; z < sizes[2]; ++z) 
    { 
     data[z] = Mat(sizes[0], sizes[1], CV_32F, float(sizes[2] - z)); 
    } 

    Mat1f some_matrix(sizes[0], sizes[1]); 
    randu(some_matrix, 0.f, 100.f); // some random values 

    // Set the n-th z-plane to some_matrix 
    int z = 0; 
    data[z] = some_matrix; 

    return 0; 
} 
0

Вот фрагмент кода для доступа к пикселю с канала, вы можете попробовать его.

int dim[3] = { 5,5,25 }; 
Mat A(3, dim, CV_32FC1, Scalar::all(0)); 

for (int m = 0; m < 5; m++) 
{ 
    for (int n = 0; n < 5; n++) 
    { 
    for (int a = 0; a < 25; a++) // no of channels 
    { 
     cout << A.at<cv::Vec3f>(m,n)[a] << endl; 
    } 
    } 
}