¿Usar iOS acelerar el marco para el procesamiento de señales 2D en imágenes que no sean de dos personas?

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

Pregunta

// editar ...

Estoy editando mi pregunta ligeramente para abordar el problema de trabajar específicamente con imágenes no potenciales de dos. Tengo una estructura básica que funciona con imágenes cuadradas de grises de grises con tamaños como 256x256 o 1024x1024, pero no puedo ver cómo generalizar a las imágenes de tamaño arbitrariamente. Las funciones de FFT parecen querer que incluya el log2 del ancho y la altura, pero luego no está claro cómo desempacar los datos resultantes, o si los datos no se están revolviendo. Supongo que lo obvio que debe hacer sería centrar la imagen NPOT dentro de una imagen más grande, toda la imagen negra y luego ignorará los valores en esas posiciones al mirar los datos. Pero preguntándose si hay una forma menos incómoda de trabajar con datos NPOT.

// ... final de edición

Estoy teniendo un poco de problemas con la documentación marco de aceleración. Normalmente usaría FFTW3, pero tengo problemas para compilar eso para compilar en un dispositivo iOS real (consulte este Pregunta ). ¿Alguien puede apuntarme a una implementación súper simple con acelerar que hace algo como lo siguiente:

1) convierte los datos de la imagen en una estructura de datos apropiada que se puede pasar a los métodos FFT de Accelerate.
En FFTW3, a su más sencillo, utilizando una imagen de escala de grises, esto implica colocar los bytes sin firmar en una matriz "FFTW_COMPLEX", que es simplemente una estructura de dos flotadores, uno que sostiene el valor real y el otro lo imaginario (y donde está el imaginario es inicializado a cero para cada píxel).

2) Toma esta estructura de datos y realiza un FFT en él.

3) Imprime la magnitud y la fase.

4) Realiza un IFFT en él.

5) recrea la imagen original de los datos resultantes de la IFFT.

Aunque este es un ejemplo muy básico, tengo problemas para usar la documentación del sitio de Apple. Lo mismo respuesta por pi aquí es muy útil, pero sigo siendo Algo confundido sobre cómo usar acelerar para hacer esta funcionalidad básica utilizando una imagen 2D de escala de grises (o color).

¿De todos modos, cualquier puntero o especialmente algún código de trabajo simple que procese una imagen 2D sería extremadamente útil?

\\\ edit \\\

De acuerdo, después de tomar un tiempo para sumergirse en la documentación y un código muy útil en Pkmital's GitHub Repo , tengo algún código de trabajo que pensé que publicaría desde 1), me tomó un tiempo resolverlo y 2) desde que tengo un par de Preguntas restantes ...

Inicializar el plan FFT ". Suponiendo una imagen de dos potencia cuadrada:

#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);

Pase en una matriz de bytes para una imagen cuadrada de dos escalas de grises y convertirla en un complejo_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;
    }
}

Ejecute el FFT en los datos de la imagen transformados, luego tome la magnitud y la fase:

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]);
}

Ahora puede ejecutar un IFFF en los datos OUTP_FFT para obtener la imagen original ...

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 );

o puede ejecutar un ácido iffi en la magnitud para obtener una autocorrelación ...

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 );

Finalmente, puede colocar los resultados de IFFF en una matriz de imágenes:

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

No he descubierto cómo usar el marco de aceleración para manejar las imágenes que no sean potenciales. Si supongo suficiente memoria en la configuración, puedo hacer un FFT, seguido de un ácido iffi para obtener mi imagen original. Pero si trata de hacer una autocorrelación (con la magnitud del FFT), entonces mi imagen obtiene resultados de WONKY. No estoy seguro de la mejor manera de presentar la imagen de manera adecuada, así que, con suerte, alguien tenga una idea de cómo hacerlo. (O comparta una versión de trabajo del método VDSP_CONV!)

¿Fue útil?

Solución

Yo diría que para realizar trabajos en tamaños de imágenes arbitrarias, todo lo que tiene que hacer es el tamaño de su matriz de valor de entrada adecuadamente a la siguiente potencia de 2.

La parte difícil es dónde colocar sus datos de imagen originales y con qué rellenar. Lo que realmente está tratando de hacer a la imagen o la mina de datos de la imagen es crucial.

En el PDF vinculado a continuación, preste especial atención al párrafo justo por encima de 12.4.2 http://www.mathcs.org/java/programs/fft /Fftinfo/c12-4.pdf

Mientras que los anteriores hablan sobre la manipulación a lo largo de 2 ejes, podríamos realizar una idea similar a la segunda dimensión, y seguir a la segunda dimensión. Si soy correcto, entonces este ejemplo podría aplicar (y esto no es de ninguna manera un algoritmo exacto todavía):

Digamos que tenemos una imagen que es 900 por 900: Primero podríamos dividir la imagen en tiras verticales de 512, 256, 128 y 4. Luego procesaríamos 4 1D FFTs para cada fila, una para los primeros 512 píxeles, la siguiente para los siguientes 256 píxeles, la siguiente para los siguientes 128, luego la última para los 4. Dado que la salida del FFT es esencialmente la popularidad De frecuencia, entonces estos podrían simplemente agregarse (desde la perspectiva de la frecuencia de la frecuencia, no el desplazamiento angular). Luego podríamos presionar esta misma técnica hacia la 2ª dimensión. En este punto, habríamos tomado en consideración cada píxel de entrada sin tener que cojear realmente.

Esto es realmente solo alimento para el pensamiento, no lo he probado yo mismo, y de hecho debería investigar esto yo mismo. Si realmente está haciendo este tipo de trabajo en este momento, es posible que tenga más tiempo que yo en este punto, sin embargo.

Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top