// EDITAR ...¿Cómo usar IOS Accelerate Framework para el procesamiento de señal 2D en imágenes que no son de Power-of-Two?
Estoy editando mi pregunta ligeramente para abordar el problema de trabajar específicamente con imágenes que no se basan en el poder de dos. Tengo una estructura básica que funciona con imágenes cuadradas en escala de grises con tamaños como 256x256 o 1024x1024, pero no puedo ver cómo generalizar a imágenes de tamaño arbitrario. Las funciones fft parecen querer que incluya el log2 del ancho y el alto, pero no está claro cómo desempaquetar los datos resultantes, o si los datos no solo están codificados. Supongo que lo más obvio sería centrar la imagen npot dentro de una imagen negra más grande y luego ignorar los valores en esas posiciones cuando se observan los datos. Pero me pregunto si hay una forma menos incómoda de trabajar con datos npot.
//...END EDITAR
estoy teniendo un poco de problemas con la documentación Marco Acelerar. Normalmente usaría FFTW3, pero estoy teniendo problemas para compilar en un dispositivo IOS real (vea esto question). ¿Alguien puede indicarme una implementación súper simple utilizando Accelerate que hace algo como lo siguiente:
1) Convierte los datos de imagen en una estructura de datos apropiada que se puede pasar a los métodos de aceleración FFT.
En FFTW3, en su forma más simple, usando una imagen en escala de grises, esto implica colocar los bytes sin signo en una matriz "fftw_complex", que es simplemente una estructura de dos flotantes, uno sosteniendo el valor real y el otro el imaginario (y donde el imaginary se inicializa a cero para cada píxel).
2) Toma esta estructura de datos y realiza una FFT en ella.
3) Imprime la magnitud y la fase.
4) Realiza una prueba 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 utilizar la documentación del sitio de Apple. El SO answer by Pi here es muy útil, pero todavía estoy un poco confundido acerca de cómo usar Accelerate para hacer esta funcionalidad básica usando una imagen 2D en escala de grises (o color).
De todos modos, cualquier puntero o especialmente algún código de trabajo simple que procese una imagen en 2D sería extremadamente útil.
\\\ EDITAR \\\
bien, después de tomar algún tiempo para sumergirse en la documentación y algo de código muy útil en SO, así como en pkmital's github repo, Tengo algo de código de trabajo que pensé 'publicación desde 1) me tomó un tiempo para resolverlo y 2) ya que tengo un par de preguntas restantes ...
Inicializar FFT "plan".Suponiendo una imagen cuadrada de potencias de dos:
#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);
Pass en una matriz de bytes para una imagen cuadrada de potencia de dos niños en escala de grises y convertirlo en un COMPLEX_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;
}
}
Ejecutar la FFT en los datos de imagen transformada, a continuación, coger la magnitud y 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 se puede ejecutar una IFFT sobre los datos out_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 una IFFT sobre la magnitud de conseguir 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);
Por último, puede poner los resultados IFFT nuevo en una matriz de imagen:
for (UInt32 i = 0; i < numElements; i++) {
t->data[i] = (int) (out_ifft.realp[i] * 255.0);
}
I no he descubierto cómo usar el marco Accelerate para manejar imágenes que no sean de la potencia de dos. Si asigno suficiente memoria en la configuración, entonces puedo hacer una FFT, seguida de una IFFT para obtener mi imagen original. Pero si intento hacer una autocorrelación (con la magnitud de la FFT), entonces mi imagen obtiene resultados vacilantes. No estoy seguro de la mejor manera de rellenar la imagen adecuadamente, así que espero que alguien tenga una idea de cómo hacer esto. (O comparta una versión de trabajo del método vDSP_conv!)
Parece que solo está haciendo autocorrelación aquí? Pensé que Accelerate/vDSP ya tenía funciones de autocorrelación para que no tuvieras que hacer las tuyas con FFT/IFFT, etc. –
Hola, el vDSP_acor no parece existir realmente en la biblioteca Accelerate.vDSP_conv existe, pero me está dando resultados extraños ... quizás lo estoy usando incorrectamente para hacer una autocorrelación de imágenes. Si usted (o alguien) tiene un ejemplo de trabajo para usar vDSP_conv para la autocorrelación, sería genial verlo. Parte del problema es solo que es confuso en cuanto a qué datos se esperan y se envían, etc. –