Edit: J'ai téléchargé le vecteur sur Drive sous forme de fichier texte, au cas où quelqu'un voudrait y jeter un coup d'œil: https://drive.google.com/file/d/0B0wsPU8YebRQbDUwNFYza3ljSnc/view?usp=sharing

J'essaye de remodeler mon vecteur h dans un tableau 3D. h contient 295788 éléments. Dans ce cas height = 314, width = 314 et depth = 3. Fondamentalement, ce que j'essaie de faire, c'est ce que MATLAB fait avec sa fonction de remodelage.

h = reshape(h, height, width, depth)

C'est ma tentative jusqu'à présent, mais quand je l'imprime, tout ce que je vois, ce sont des zéros, ce qui n'est pas juste. J'ai vérifié que h contient les nombres que j'attends.

vector<vector<vector<double> > > array3D;

int height = 314, width = 314, depth = 3;
// Set up sizes
array3D.resize(height);
for (int i = 0; i < height; ++i) {
    array3D[i].resize(width);

    for (int j = 0; j < width; ++j)
        array3D[i][j].resize(depth);
}

for (int i = 0; i < height; i++)
{
    array3D[i][0][0] = h[i];
    for (int j = 0; j < width; j++)
    {
        array3D[i][j][0] = h[i+j];
        for (int k = 0; k < depth; k++)
        {
            array3D[i][j][k] = h[i+j+k];
        }
    }
}

Impression:

for (vector<vector<vector<double>>>::const_iterator i = array3D.begin(); i != array3D.end(); ++i)
{
    for (vector<vector<double>>::const_iterator j = i->begin(); j != i->end(); ++j)
    {
        for (vector<double>::const_iterator k = j->begin(); k != j->end(); ++k)
        {
            cout << *k << ' ';
        }
    }
}

Ma question est donc la suivante: comment convertir correctement mon vecteur en un tableau 3D?

1
asdfghjkl 1 mai 2017 à 05:26

3 réponses

Meilleure réponse

J'ai réussi à le faire en utilisant Eigen :: Tensor comme suggéré par Henri Menke. J'ai fini par créer un tableau pour la matrice initiale 314x314x3, puis un autre pour la matrice 300x300x3. Ce n'est ni rapide ni joli, mais pour l'instant c'est ce que je pourrais trouver. Ressemble à ça.

Pour clarifier: margin est calculé plus haut dans le code, mais dans cet exemple avec la matrice 314x314x3 c'est margin=7. h est un vecteur avec 295788 éléments. nrh=314, nch=314 et nradii=3.

Tensor<int, 3> t(nrh, nch, nradii);
int counter = 0;
for (int k = 0; k < nradii; k++)
{
    for (int col = 0; col < nch; col++)
    {
        for (int row = 0; row < nrh; row++) 
        {
            t(row, col, k) = h[counter];
            counter += 1;
        }
    }
}

int height = nrh - margin * 2;
int width = nch - margin * 2;
int depth = nradii;
Tensor<int, 3> out(height, width, depth);
int count1 = 0, count2 = 0, count3 = 0;

for (int k = 0; k < depth; k++)
{
    for (int j = margin; j < nch - margin; j++)
    {
        for (int i = margin; i < nrh - margin; i++)
        {
            out(count1, count2, count3) = t(i, j, k);
            count1 += 1;
        }
        count1 = 0;
        count2 += 1;
    }
    count2 = 0;
    count3 += 1;
}

Edit: Solution n ° 2 avec Tensor.slice ()

int height = nrh - margin * 2;
int width = nch - margin * 2;
int depth = nradii;
Tensor<int, 3> tensor(height, width, depth);
DSizes<ptrdiff_t, 3> indices(margin, margin, 0);
DSizes<ptrdiff_t, 3> sizes(height, width, nradii);
tensor = t.slice(indices, sizes);
0
asdfghjkl 3 mai 2017 à 08:17

En fait, la structure de votre code est déjà correcte, cependant, il y a deux erreurs:

  • Les lignes

    array3D[i][0][0] = h[i];
    

    et

    array3D[i][j][0] = h[i+j];
    

    sont inutiles. Vous écrasez ces entrées plus tard avec la ligne

    array3D[i][j][k] = h[i+j+k];
    
  • Le calcul de l'index pour h[] est erroné: vous devez multiplier l'index de ligne par la longueur d'une ligne avant d'ajouter l'index de cellule. Le devoir devrait ressembler à ceci:

    array3D[i][j][k] = h[(i*width+j)*depth+k];
    

    Sinon, vous obtiendrez le même résultat pour (i, j, k) == (3, 2, 1) que pour (i, j, k) == (1, 3, 2), ce qui est évidemment faux. Dans le calcul de l'indice ci-dessus, j'ai supposé que k est la dimension qui évolue le plus rapidement. Si ce n'est pas l'ordre dans lequel vos données sont stockées dans h, vous devez modifier les positions de i, j et k et ajuster les facteurs en conséquence.

En mettant cela ensemble, votre boucle d'affectation devrait se lire:

for (int i = 0; i < height; i++) {
    for (int j = 0; j < width; j++) {
        for (int k = 0; k < depth; k++) {
            array3D[i][j][k] = h[(i*width+j)*depth+k];
        }
    }
}

Légèrement hors sujet:
Si vous utilisiez C au lieu de C ++, vous pourriez "simplement" faire ceci:

size_t dataSize;
//Create a real 3D array with the dimensions (height, width, depth).
double (*array3D)[width][depth] = malloc(dataSize = height*sizeof(*array3D));
//Copy over the data from the file.
memcpy(array3D, h, dataSize);


//Print the array contents:
for (int i = 0; i < height; i++) {
    for (int j = 0; j < width; j++) {
        for (int k = 0; k < depth; k++) {
            printf("%d ", array3D[i][j][k]);
        }
    }
}

Cela utilise un véritable tableau 3D au lieu d'un tableau de pointeurs vers des tableaux de pointeurs vers des tableaux de doubles (ce qui est à peu près ce qu'est un vector<vector<vector<double>>>). Cependant, cela ne peut pas être fait en C ++ car C ++ ne permet pas les types de tableaux avec des tailles dynamiques comme le fait C.

0
cmaster - reinstate monica 3 mai 2017 à 08:45

Que diriez-vous:

array3D[i][j][k] = h[i*(depth*width)+j*depth+k];

Cela peut ou non scanner le vecteur dans le bon ordre.

Remarquez comment, lorsque l'index k réinitialise l'index j, vous passez exactement à un jusqu'à ce que l'index j se réinitialise, auquel cas i s'incrémente et pareil. Il est facile de montrer que ce calcul lit chaque élément exactement une fois.

Je m'attendrais normalement à un width, height puis depth et vous numérisez dans l'ordre inverse!

Note de bas de page: En fonction de l'application, il peut être intéressant d'accéder simplement au vecteur en utilisant cette approche. En général, cela s'avère plus rapide que d'accéder à un vecteur de vecteurs de vecteurs. Cela peut être pertinent lorsqu'il s'agit de tableaux massifs.

0
Persixty 3 mai 2017 à 08:28