2012-05-22 8 views
13

// 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!)

+0

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. –

+0

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. –

Respuesta

3

Yo diría que para realizar trabajos en tamaños de imagen arbitrarios, todo lo que tiene que hacer es dimensionar su matriz de valores de entrada apropiadamente a la siguiente potencia de 2.

La parte difícil es dónde poner los datos de su imagen original y qué llenar. Lo que realmente intentas hacer con la imagen o los datos de la imagen es crucial.

En el PDF vinculado a continuación, prestar especial atención a la párrafo justo por encima 12.4.2 http://www.mathcs.org/java/programs/FFT/FFTInfo/c12-4.pdf

Si bien lo anterior habla de la manipulación a lo largo de 2 ejes, podríamos potentialy realizar una idea similar antes de la segunda dimensión y siguiendo a la segunda dimensión. Si soy correcto, entonces este ejemplo podría aplicarse (y esto de ningún modo es un algoritmo exacto todavía):

decir que tenemos una imagen que es 900 por 900: primero podríamos dividir la imagen en tiras verticales de 512, 256, 128 y 4. Procesamos 4 FFT 1D para cada fila, una para los primeros 512 píxeles, la siguiente para los siguientes 256 píxeles, la siguiente para las siguientes 128, luego la última para las 4 restantes. la salida de la FFT es esencialmente la popularidad de la frecuencia, entonces estos simplemente podrían ser agregados (desde la perspectiva de la frecuencia ÚNICA, no la compensación angular). Podríamos empujar esta misma techniquie hacia la 2da dimensión. En este punto, habríamos tenido en cuenta cada píxel de entrada sin tener que rellenar.

Esto es realmente solo una cuestión de reflexión, no lo he intentado yo mismo, y de hecho debería investigar esto por mi cuenta. Si realmente está haciendo este tipo de trabajo en este momento, puede que tenga más tiempo que yo en este momento.

+0

hmm, idea interesante ... –

+0

Esto no es como procesar una señal de audio de 20 segundos en trozos de 5 segundos. Es más como procesar una señal de audio dividiendo entre 0-10khz y 10khz-20khz. Obtendrá bandas diferentes de cada una, así que agregará 2khz con 12khz, o algo así ... –

Cuestiones relacionadas