Utilisation du cadre d'accélération iOS pour le traitement du signal 2D sur des images non power-de-deux?

StackOverflow https://stackoverflow.com//questions/10708667

Question

// edit ...

Je modifie légèrement ma question pour résoudre le problème de travailler spécifiquement avec des images non power-de-deux. J'ai une structure de base qui fonctionne avec des images en niveaux de gris carrées avec des tailles telles que 256x256 ou 1024x1024, mais vous ne pouvez pas voir comment généraliser avec des images de la taille arbitraire. Les fonctions FFT semblent vouloir que vous incluiez le log2 de la largeur et de la hauteur, mais il est difficile de déballer les données résultantes ou si les données ne sont pas simplement brouillées. Je suppose que la chose évidente à faire serait de centrer l'image NPOT dans une image plus grande, de toutes les images noires, puis d'ignorer toutes les valeurs dans ces positions lors de la recherche des données. Mais se demandant s'il y a une façon moins gênante de travailler avec des données NPOT.

// ... fin d'édition

J'ai un peu de problèmes avec la documentation de cadre accéléré. J'utiliserais normalement FFTW3, mais je rencontre des difficultés pour compiler sur un appareil iOS actuel (voir ceci question ). Quelqu'un peut-il me diriger à une implémentation super simple à l'aide d'accélérer qui fait quelque chose comme ce qui suit:

1) active les données d'image en une structure de données appropriée pouvant être transmise aux méthodes FFT d'accélération.
À FFTW3, à sa plus simple, à l'aide d'une image en niveaux de gris, cela implique de placer les octets non signés dans un tableau "FFTW_COMPLEX", qui est simplement une structure de deux flotteurs, une tenant la valeur réelle et l'autre l'imaginaire (et où l'imaginaire est initialisé à zéro pour chaque pixel).

2) prend cette structure de données et effectue une FFT dessus.

3) imprime la magnitude et la phase.

4) effectue un ifft dessus.

5) recrée l'image d'origine à partir des données résultant de l'IFFT.

Bien que ce soit un exemple très fondamental, j'ai du mal à utiliser la documentation du site d'Apple. Le so Réponse de PI ici est très utile, mais je suis toujours Un peu confus sur la manière d'utiliser accélérer pour faire cette fonctionnalité de base à l'aide d'une image 2D de gris (ou de couleur).

Quoi qu'il en soit, tous les pointeurs ou surtout un code de travail simple qui traite une image 2D serait extrêmement utile!

\\\ edit \\\\\

D'accord, après avoir pris du temps pour plonger dans la documentation et un code très utile sur, ainsi que sur GitHub Repo de PKMital, j'ai un code de travail que je pensais poster depuis 1) il m'a fallu un certain temps pour le comprendre et 2) depuis que j'ai un couple de Questions restantes ...

Initialiser la FFT "Plan". En supposant une alimentation carrée de deux image:

#include <Accelerate/Accelerate.h>
...
UInt32 N = log2(length*length);
UInt32 log2nr = N / 2; 
UInt32 log2nc = N / 2;
UInt32 numElements = 1 << ( log2nr + log2nc );
float SCALE = 1.0/numElements;
SInt32 rowStride = 1; 
SInt32 columnStride = 0;
FFTSetup setup = create_fftsetup(MAX(log2nr, log2nc), FFT_RADIX2);

Passez une matrice d'octet pour une image en niveaux de gris de puissance carrée et transformez-la en un complexe_split:

COMPLEX_SPLIT in_fft;
in_fft.realp = ( float* ) malloc ( numElements * sizeof ( float ) );
in_fft.imagp = ( float* ) malloc ( numElements * sizeof ( float ) );

for ( UInt32 i = 0; i < numElements; i++ ) {
    if (i < t->width * t->height) {
      in_fft.realp[i] = t->data[i] / 255.0;
      in_fft.imagp[i] = 0.0;
    }
}

Exécutez la FFT sur les données d'image transformées, puis prenez la magnitude et la phase:

COMPLEX_SPLIT out_fft;
out_fft.realp = ( float* ) malloc ( numElements * sizeof ( float ) );
out_fft.imagp = ( float* ) malloc ( numElements * sizeof ( float ) );

fft2d_zop ( setup, &in_fft, rowStride, columnStride, &out_fft, rowStride, columnStride, log2nc, log2nr, FFT_FORWARD );

magnitude = (float *) malloc(numElements * sizeof(float));
phase = (float *) malloc(numElements * sizeof(float));

for (int i = 0; i < numElements; i++) {
   magnitude[i] = sqrt(out_fft.realp[i] * out_fft.realp[i] + out_fft.imagp[i] * out_fft.imagp[i]) ;
   phase[i] = atan2(out_fft.imagp[i],out_fft.realp[i]);
}

Vous pouvez maintenant exécuter un ifft sur les données OUT_FFT pour obtenir l'image d'origine ...

COMPLEX_SPLIT out_ifft;
out_ifft.realp = ( float* ) malloc ( numElements * sizeof ( float ) );
out_ifft.imagp = ( float* ) malloc ( numElements * sizeof ( float ) );
fft2d_zop (setup, &out_fft, rowStride, columnStride, &out_ifft, rowStride, columnStride, log2nc, log2nr, FFT_INVERSE);   

vsmul( out_ifft.realp, 1, SCALE, out_ifft.realp, 1, numElements );
vsmul( out_ifft.imagp, 1, SCALE, out_ifft.imagp, 1, numElements );

ou vous pouvez exécuter un ifft sur la magnitude pour obtenir une autocorrélation ...

COMPLEX_SPLIT in_ifft;
in_ifft.realp = ( float* ) malloc ( numElements * sizeof ( float ) );
in_ifft.imagp = ( float* ) malloc ( numElements * sizeof ( float ) );
for (int i = 0; i < numElements; i++) {
  in_ifft.realp[i] = (magnitude[i]);
  in_ifft.imagp[i] = 0.0;
}

fft2d_zop ( setup, &in_fft, rowStride, columnStride, &out_ifft, rowStride, columnStride, log2nc, log2nr, FFT_INVERSE );      

vsmul( out_ifft.realp, 1, SCALE, out_ifft.realp, 1, numElements );
vsmul( out_ifft.imagp, 1, SCALE, out_ifft.imagp, 1, numElements );

Enfin, vous pouvez mettre les résultats de l'IFFT dans une matrice d'image:

for ( UInt32 i = 0; i < numElements; i++ ) {
  t->data[i] = (int) (out_ifft.realp[i] * 255.0);
}     

Je n'ai pas compris comment utiliser le cadre d'accélération pour gérer des images non power-de-deux. Si j'alloque suffisamment de mémoire dans la configuration, je peux faire une FFT, suivie d'un ifft pour obtenir mon image d'origine. Mais si vous essayez de faire une autocorrélation (avec la magnitude de la FFT), alors mon image obtient des résultats de Wonky. Je ne suis pas sûr de la meilleure façon de rembourrer l'image de manière appropriée, alors j'espère que quelqu'un a une idée de la façon de faire cela. (Ou partagez une version de travail de la méthode VDSP_CONV!)

Était-ce utile?

La solution

Je dirais que pour effectuer des travaux sur des tailles d'image arbitraires, tout ce que vous avez à faire est de la taille de votre réseau de valeur d'entrée de manière appropriée à la puissance suivante de 2.

La partie difficile est l'endroit idéal pour mettre vos données d'image d'origine et quoi remplir. Ce que vous essayez vraiment de faire à l'image ou à la mine de données de l'image est crucial.

Dans le PDF lié ci-dessous, payez une attention particulière au paragraphe au-dessus de 12.4.2 http://www.mathcs.org/java/programs/fft /Fftinfo/c12-4.pdf

Bien que ce qui précède parle de la manipulation sur 2 axes, nous pourrions effectuer une idée de potentiellement une idée similaire avant la deuxième dimension et suivre la deuxième dimension. Si je corrige, cet exemple pourrait peut-être s'appliquer (et cela ne signifie pas encore un algorithme exact):

dire que nous avons une image de 900 par 900: Nous pourrions d'abord diviser l'image en bandes verticales de 512, 256, 128 et 4. Nous traiterions ensuite 4 FFT 1D pour chaque ligne, une pour les 512 premiers pixels, la suivante pour les 256 pixels suivants, la suivante pour les 128 suivants, puis le dernier pour le reste 4. Étant donné que la sortie de la FFT est essentiellement en popularité. de fréquence, alors celles-ci pourraient simplement être ajoutées (de la perspective de la fréquence que, pas du décalage angulaire). Nous pourrions alors pousser cette même technique vers la 2e dimension. À ce stade, nous aurions pris en considération chaque pixel d'entrée sans avoir à avoir à la notes.

Ce n'est vraiment que de la nourriture pour la pensée, je n'ai pas essayé cela moi-même et devriez en effet la recherche moi-même. Si vous faites vraiment ce genre de travail en ce moment, vous pouvez avoir plus de temps que moi à ce stade.

Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top