Programaticamente encuentre imágenes trémulas o fuera de foco

La mayoría de las cámaras móviles modernas tiene una familia de técnicas llamada Estabilización de Imagen para reducir los efectos inestables en las fotografías debido al movimiento de la lente de la cámara o hardware asociado. Pero todavía un buen número de cámaras móviles producen fotografías inestables. ¿Existe un algoritmo o método confiable que se puede implementar en dispositivos móviles, específicamente en Android para encontrar si una imagen de entrada dada es inestable o no? No espero que el algoritmo estabilice la imagen de entrada, pero el algoritmo / método debe devolver de forma fiable un booleano definitivo si la imagen es inestable o no. No tiene que ser Java, pero también puede ser C / C ++ para que uno pueda construirlo a través del kit nativo y exponer las API a la capa superior. La siguiente ilustración describe el resultado esperado. Además, esta pregunta se ocupa de problemas de imagen única, por lo que múltiples soluciones basadas en marcos no funcionará en este caso. Se trata específicamente de imágenes, no de vídeos.

Introduzca aquí la descripción de la imagen

Las imágenes fuera de foco implican que a) los bordes están borrosos, por lo que cualquier operador basado en gradiente tendrá valores bajos comparados con la luminancia en la imagen b) los bordes serán borrosos, por lo que cualquier operador basado en curvatura tendrá valores bajos c) para Las imágenes temblorosas, los píxeles se correlacionarán con otros píxeles en la dirección de la sacudida (una traducción o una rotación)

Tomé tu foto en gimp, apliqué Sobel para a) y Laplacian para b) (disponible en openCV), y obtuve imágenes que son mucho más oscuras en la parte anterior.

Calcular umbrales para imágenes generales sería bastante difícil, supongo.

¿Se trata de una secuencia de vídeo o una sola imagen

En caso de flujo de vídeo : La mejor manera es calcular la diferencia entre cada 2 cuadros adyacentes. Y marque cada píxel con la diferencia. Cuando la cantidad de estos píxeles es baja – usted está en un marco no inestable. Tenga en cuenta que este método no comprueba si la imagen está enfocada, pero sólo está diseñada para combatir el desenfoque de movimiento en la imagen. Su implementación debe incluir lo siguiente

  1. Para cada trama 'i' – normalizar la imagen (trabajar con nivel de gris, al trabajar con puntos flotantes normalizar la media a 0 y la desviación estándar a 1)
  2. Guardar el marco de vídeo anterior.
  3. En cada nuevo fotograma de vídeo se calcula la diferencia en píxeles entre las imágenes y se cuenta la cantidad de píxeles para los que la diferencia supera un cierto umbral. Si la cantidad de estos píxeles es demasiado alta (digamos> 5% de la imagen), esto significa que el movimiento entre el fotograma anterior y el fotograma actual es grande y se espera un desenfoque de movimiento. Cuando la persona sostiene el teléfono con firmeza, verá una fuerte caída en la cantidad de píxeles que ha cambiado.
  4. Si sus imágenes están representadas no en coma flotante pero en punto fijo (digamos 0..255), puede combinar los histogramas de las imágenes antes de la substracción para reducir el ruido.
  5. Siempre y cuando usted está recibiendo imágenes con movimiento, simplemente dejar caer esos marcos y mostrar un mensaje al usuario "mantener el teléfono firmemente". Una vez que obtenga una buena imagen estabilizada, procesela pero mantenga recordando la anterior y realice la resta para cada fotograma de vídeo.

El algoritmo arriba debe ser lo suficientemente fuerte (lo usé en uno de mis proyectos, y funcionó como una magia).

En el caso de una sola imagen : El algoritmo anterior no resuelve las imágenes desenfocadas y es irrelevante para una sola imagen.

  1. Para resolver el enfoque, recomiendo calcular los bordes de la imagen y contar la cantidad de píxeles que tienen bordes fuertes (más alto que un umbral). Una vez que se obtiene una gran cantidad de píxeles con bordes (digamos> 5% de la imagen), se dice que la imagen está enfocada. Este algoritmo está lejos de ser perfecto y puede cometer muchos errores, dependiendo de la textura de la imagen. Recomiendo usar bordes X, Y y diagonales, pero suavizar la imagen antes de la detección de bordes para reducir el ruido.
  2. Un algoritmo más fuerte sería tomar todos los bordes (derivados) y el cálculo de su histograma (cuántos píxeles en la imagen tenía esta intensidad de borde específico). Esto se hace calculando primero una imagen de bordes y calculando un histograma de la imagen de borde. Ahora puedes analizar la forma del histograma (la distribución de la resistencia de los bordes). Por ejemplo, tomar sólo el 5% superior de píxeles con bordes más fuertes y calcular la varianza de su intensidad de borde.
  3. Dato importante: En las imágenes desenfocadas, se espera que la mayoría de los píxeles tengan una respuesta de borde muy bajo, pocos tengan una respuesta de borde medio y casi cero con una respuesta de borde fuerte. En las imágenes con enfoque perfecto todavía tiene la mayoría de los píxeles con respuesta de borde bajo, pero la relación entre la respuesta media a cambios de respuesta fuerte. Usted puede ver claramente en la forma del histograma. Es por eso que recomiendo tomar sólo un pequeño% de los píxeles con la respuesta de borde más fuerte y trabajar sólo con ellos. El resto son sólo un ruido. Incluso un algoritmo simple de tomar la proporción entre la cantidad de píxeles con respuesta fuerte dividida por la cantidad de píxeles con bordes medios será bastante bueno.

Problema de enfoque en vídeo :

  1. Si tiene una secuencia de vídeo que puede utilizar los algoritmos descritos anteriormente para la detección de foco problemático, pero en lugar de utilizar umbrales constantes, sólo actualizarlos como se ejecuta el vídeo. Eventualmente convergerán a mejores valores que las constantes predefinidas.

Última nota: El problema de detección de foco en una sola imagen es muy difícil. Hay una gran cantidad de trabajos académicos (utilizando wavelets de transformada de Fourier y otros "grandes cañones algorítmicos"). Pero el problema sigue siendo muy difícil porque cuando se está mirando una imagen borrosa no se puede saber si es la cámara la que generó el desenfoque con enfoque incorrecto, o la realidad original ya está borrosa (por ejemplo, las paredes blancas son muy borrosas, fotos tomadas En una oscuridad tienden a ser borrosa incluso bajo enfoque perfecto, imágenes de la superficie del agua, superficie de la mesa tienden a ser borrosa). De todos modos hay pocos hilos en el desbordamiento de la pila con respecto al foco en la imagen. Como éste . Por favor, lea.

También puede calcular la transformada de Fourier de la imagen y, a continuación, si hay una baja acumulación en los contenedores de alta frecuencia, entonces la imagen es probablemente borrosa. JTransform es una biblioteca razonable que proporciona FFT si desea viajar por esta ruta.

También hay un blog bastante extenso aquí sobre diferentes métodos que podrían ser usados

También hay otra pregunta sobre el desbordamiento de la pila que pide esto pero con OpenCV , OpenCV también tiene enlaces de Java y se puede utilizar en proyectos de Android por lo que esta respuesta también podría ser útil.

  • Biblioteca de OCR para Android
  • Android: BitmapFactory.decodeByteArray ofrece bitmap pixelado
  • Android ImageView Vecino más cercano
  • Uso de ImageMagick en mi aplicación Android
  • Android flood-fill algoritmo
  • Android Paper Detection con OpenCV
  • Transmisión de matriz a rsForEach en Renderscript Compute
  • Error con setPixels
  • Biblioteca de procesamiento de imágenes para Android?
  • Cómo hacer un fadein de una imagen en una pantalla de Android Activity?
  • OpenCV obtiene píxeles negros dentro del límite del contorno
  • FlipAndroid es un fan de Google para Android, Todo sobre Android Phones, Android Wear, Android Dev y Aplicaciones para Android Aplicaciones.