sociologia segun origen memetica memes meme los importancia fenomeno ensayo definicion comunicacion autores analisis algorithm image-processing

algorithm - segun - Algoritmo de reducción de ojos rojos



meme y memetica (10)

Necesito implementar la reducción de ojos rojos para una aplicación en la que estoy trabajando.

Google generalmente proporciona enlaces a productos comerciales para el usuario final.

¿Conoces un buen algoritmo de reducción de ojos rojos, que podría usarse en una aplicación de GPL?


¡Primero necesitas encontrar los ojos! La forma estándar sería ejecutar un detector de bordes y luego una transformada Hough para encontrar dos círculos del mismo tamaño, pero podría haber algoritmos más fáciles para encontrar simplemente grupos de píxeles rojos.

Luego debe decidir con qué reemplazarlos, suponiendo que hay suficientes datos verdes / azules en la imagen, simplemente podría ignorar el canal rojo.

OpenCV es una muy buena biblioteca gratuita para el procesamiento de imágenes, puede ser exagerado para lo que desee, pero tiene muchos ejemplos y una comunidad muy activa. También puede buscar algoritmos de seguimiento de objetos, el seguimiento de un objeto de color en una escena es un problema muy similar y común.


Aquí está la solución de implementación de Java

public void corrigirRedEye(int posStartX, int maxX, int posStartY, int maxY, BufferedImage image) { for(int x = posStartX; x < maxX; x++) { for(int y = posStartY; y < maxY; y++) { int c = image.getRGB(x,y); int red = (c & 0x00ff0000) >> 16; int green = (c & 0x0000ff00) >> 8; int blue = c & 0x000000ff; float redIntensity = ((float)red / ((green + blue) / 2)); if (redIntensity > 2.2) { Color newColor = new Color(90, green, blue); image.setRGB(x, y, newColor.getRGB()); } } } }

Siendo los parámetros recuperados de dos rectángulos detectados por una aplicación como open cv (esto debería ser un rectángulo que involucre la posición del ojo)

int posStartY = (int) leftEye.getY(); int maxX = (int) (leftEye.getX() + leftEye.getWidth()); int maxY = (int) (leftEye.getY() + leftEye.getHeight()); this.corrigirRedEye(posStartX, maxX, posStartY, maxY, image); // right eye posStartX = (int) rightEye.getX(); posStartY = (int) rightEye.getY(); maxX = (int) (rightEye.getX() + rightEye.getWidth()); maxY = (int) (rightEye.getY() + rightEye.getHeight()); this.corrigirRedEye(posStartX, maxX, posStartY, maxY, image);


El algoritmo más simple, y aún uno muy efectivo sería poner a cero la R del triple RGB para la región de interés.

El rojo desaparece, pero los otros colores se conservan.

Una extensión adicional de este algoritmo podría implicar poner a cero el valor R solo para los triples, donde el rojo es el color dominante (R> G y R> B).


El proyecto de código abierto Paint.NET tiene una implementación en C #.


Esta es una implementación más completa de la respuesta provista por Benry:

using SD = System.Drawing; public static SD.Image ReduceRedEye(SD.Image img, SD.Rectangle eyesRect) { if ( (eyesRect.Height > 0) && (eyesRect.Width > 0)) { SD.Bitmap bmpImage = new SD.Bitmap(img); for (int x=eyesRect.X;x<(eyesRect.X+eyesRect.Width);x++) { for (int y=eyesRect.Y;y<(eyesRect.Y+eyesRect.Height);y++) { //Value of red divided by average of blue and green: SD.Color pixel = bmpImage.GetPixel(x,y); float redIntensity = ((float)pixel.R / ((pixel.G + pixel.B) / 2)); if (redIntensity > 2.2f) { // reduce red to the average of blue and green bmpImage.SetPixel(x, y, SD.Color.FromArgb((pixel.G + pixel.B) / 2, pixel.G, pixel.B)); pixel = bmpImage.GetPixel(x,y); // for debug } } } return (SD.Image)(bmpImage); } return null; }



Llego tarde a la fiesta aquí, pero para futuros buscadores he usado el siguiente algoritmo para una aplicación personal que escribí.

En primer lugar, el usuario selecciona la región a reducir y pasa al método de reducción de ojos rojos como punto central y radio. El método recorre cada píxel dentro del radio y realiza el siguiente cálculo:

//Value of red divided by average of blue and green: Pixel pixel = image.getPixel(x,y); float redIntensity = ((float)pixel.R / ((pixel.G + pixel.B) / 2)); if (redIntensity > 1.5f) // 1.5 because it gives the best results { // reduce red to the average of blue and green bm.SetPixel(i, j, Color.FromArgb((pixel.G + pixel.B) / 2, pixel.G, pixel.B)); }

Realmente me gustan los resultados de esto porque mantienen la intensidad del color, lo que significa que el reflejo de la luz del ojo no se reduce. (Esto significa que los ojos mantienen su aspecto "vivo").



Si nadie más viene con una respuesta más directa, siempre puedes descargar el código fuente de GIMP y ver cómo lo hacen.


una gran biblioteca para encontrar ojos está openCV . es muy rico en funciones de procesamiento de imágenes. vea también this documento con el título "Detección automática de ojos rojos" de Ilia V. Safonov.