En esta entrada vamos a exponer un sencillo método para eliminar los ojos rojos en un fotografía. El método no es completamente automático, es decir, no va a detectar la posición de los ojos sino que el usuario tiene que dar las coordenadas y el radio del círculo de los ojos.
Abrimos un nuevo proyecto en Visual Studio y creamos el siguiente formulario.
![]() |
Formulario para detectar ojos rojos |
Como podemos observar está compuesto de varios Textbox donde se introducirán los datos, un Picturebox donde estará la imagen, 3 botones y abajo una barra StatusStrip al que se le ha añadido un ToolStripStatusLabel que será donde se muestren las coordenadas del puntero con respecto al Picturebox. Una vez tenemos el formulario creado, vamos a explicar el proceso para detectar y corregir los ojos rojos.
La función que corrige los ojos rojos es la siguiente:
Private Function EliminarOjosRojos(ByVal bmp As Bitmap, ByVal CentroOjo As Point, ByVal radioOjo As Integer, Optional valorMinimo As Double = 1.5) Dim bmpCirculo As New Bitmap(bmp) Dim bmpCopia As New Bitmap(bmp) Dim gr As Graphics = Graphics.FromImage(bmpCirculo) 'Le damos un color poco problable para un ojo (amarillo puro) ya que luego evaluaremos el cuadrado circunscrito a la circunferencia Dim relleno As Brush = New SolidBrush(Color.FromArgb(255, 255, 255, 0)) gr.FillEllipse(relleno, CentroOjo.X - radioOjo, CentroOjo.Y - radioOjo, radioOjo * 2, radioOjo * 2) Dim bmpPintado As New Bitmap(bmpCirculo) 'Almacenamos una copia de la imagen con la primera línea Dim rojo, verde, azul As Integer 'Recorremos el cuadrado circunscrito a la circunferencia For i = CentroOjo.X - (radioOjo - 1) To CentroOjo.X + (radioOjo + 1) For j = CentroOjo.Y - (radioOjo - 1) To CentroOjo.Y + (radioOjo + 1) 'Si el valor es amarillo (es decir, es el círculo que creamos) If bmpPintado.GetPixel(i, j) = (Color.FromArgb(255, 255, 255, 0)) Then Dim intensidadRojo As Double verde = bmp.GetPixel(i, j).G azul = bmp.GetPixel(i, j).B rojo = bmp.GetPixel(i, j).R intensidadRojo = (rojo / ((verde + azul) / 2)) 'Hacemos la comprobación de que sea un ojo rojo (el valor más adecuado por norma general es 1.5) If intensidadRojo > valorMinimo Then 'Creamos el valor rojo a partir del verde y azul rojo = (verde + azul) / 2 bmpCopia.SetPixel(i, j, Color.FromArgb(rojo, verde, azul)) End If End If Next Next Return bmpCopia End Function
A esta función se le envía la imagen original (en formato Bitmap), el centro del ojo (coordenadas X e Y), el radio del ojo y opcionalmente el valor mínimo. Lo que hará será crear un círculo de color amarillo con los datos recibidos y dentro del cuadrado circunscrito a ese círculo evaluará los píxeles y, si son amarillos (es decir, están dentro del círculo), entonces evalúa el valor original de ese píxel. Si ese valor original está dentro del mínimo que se le pasa a la función (por defecto es 1.5) entones actuará calculando el nuevo valor del color rojo como la media de los canales verde y azul.
Con respecto al parámetro valor mínimo, lo que hace es calcular, para cada píxel analizado, la siguiente operación, (rojo / ((verde + azul) / 2)), y si es superior el resultado al valor mínimo (por defecto 1.5), entonces quiere decir que vamos a aplicar la modificación al píxel.
Como observamos la función no es perfecta pero es una sencilla forma de eliminar los ojos rojos.
Adicionalmente, para mostrar las coordenadas del cursor dentro del Picturebox utilizaremos el evento MouseMove asociado al propio PictureBox.
Private Sub PictureBox1_MouseMove1(sender As Object, e As MouseEventArgs) Handles PictureBox1.MouseMove ToolStripStatusLabel1.Text = "(" & e.Location.X & "," & e.Location.Y & ") px" End Sub
El resultado tras aplicar la función es el siguiente:
![]() |
Imagen con ojos rojos corregidos |
Para descargar el código fuente, haz clic en la imagen que hay debajo:
Más info en http://ocw.usal.es/ensenanzas-tecnicas/herramientas-informaticas-para-el-geoprocesado
No hay comentarios:
Publicar un comentario