El histograma acumulado de una imagen no es más que contar, para cada canal RGB, el número de píxeles que hay de cada componente. Por ejemplo, para el canal rojo, el número de píxeles que tienen valor 255.
Estos histogramas nos proveen de mucha información sobre la imagen y cómo poder mejorarla, por ejemplo, aumentando el ancho del histograma (aumentando el contraste). Y en esta entrada, vamos a ver cómo podemos hacerlos con Visual Basic. La forma de hacerlos será mediante una función denominada histogramaAcumulado la cual nos devolverá una matriz de 2 dimensiones que almacenará el histograma acumulado de los canales RGB.
Public Function histogramaAcumulado(ByVal bmp As Bitmap) As Integer(,) Dim Rojo, Verde, Azul As Byte 'Declaramos tres variables que almacenarán los colores Dim matrizAcumulada(2, 255) As Integer For i = 0 To bmp.Width - 1 'Recorremos la matriz For j = 0 To bmp.Height - 1 Rojo = bmp.GetPixel(i, j).R 'Asignamos el color Verde = bmp.GetPixel(i, j).G Azul = bmp.GetPixel(i, j).B 'ACumulamos los valores. matrizAcumulada(0, Rojo) += 1 matrizAcumulada(1, Verde) += 1 matrizAcumulada(2, Azul) += 1 Next Next Return matrizAcumulada End Function
La función primeramente almacena en tres variables (rojo, verde, azul) el color de cada píxel, y después, va acumulando los valores en la matriz de retorno. La matriz de retorno tiene dos dimensiones y el histograma acumulado está en el siguiente rango:
- Para el canal rojo de matrizAcumulada(0,0) a matrizAcumulada(0,255).
- Para el canal verde de matrizAcumulada(1,0) a matrizAcumulada(1,255).
- Para el canal azul de matrizAcumulada(2,0) a matrizAcumulada(2,255).
El siguiente paso, será crear un control Chart al que le añadiremos una serie denominada Histograma, y el tipo de chart será SplineArea. El resultado del formulario sería algo así:
![]() |
Formulario con histograma |
Ahora vamos a añadir el código fuente asociado a los tres botones y al load del formulario.
Dim histoAcumulado As Integer(,) 'Variable que almacenará los histogramas Private Sub Form1_Load(sender As Object, e As EventArgs) Handles MyBase.Load 'Cargamos los histogramas Dim bmp As New Bitmap(PictureBox1.Image) histoAcumulado = histogramaAcumulado(bmp) 'Ejecutamos el botón del histograma rojo Button1_Click(sender, e) End Sub 'Histograma rojo Private Sub Button1_Click(sender As Object, e As EventArgs) Handles Button1.Click 'Borramos el posible contenido del chart Chart1.Series("Histograma").Points.Clear() 'Los ponesmos del colores correspondiente Chart1.Series("Histograma").Color = Color.Red For i = 0 To 255 Chart1.Series("Histograma").Points.AddXY(i + 1, histoAcumulado(0, i)) Next End Sub 'Histograma verde Private Sub Button2_Click(sender As Object, e As EventArgs) Handles Button2.Click 'Borramos el posible contenido del chart Chart1.Series("Histograma").Points.Clear() Chart1.Series("Histograma").Color = Color.Green For i = 0 To 255 Chart1.Series("Histograma").Points.AddXY(i + 1, histoAcumulado(1, i)) Next End Sub 'Histograma azul Private Sub Button3_Click(sender As Object, e As EventArgs) Handles Button3.Click 'Borramos el posible contenido del chart Chart1.Series("Histograma").Points.Clear() Chart1.Series("Histograma").Color = Color.Blue For i = 0 To 255 Chart1.Series("Histograma").Points.AddXY(i + 1, histoAcumulado(2, i)) Next End Sub
Lo que hacemos es llamar a la función en el load del formulario y después, en función del botón pulsado, recorrer la variable que contiene el histograma (histoAcumulado) y dibujarlo en el Chart.
Puedes descargar el código fuente aquí:
Más info: http://ocw.usal.es/ensenanzas-tecnicas/herramientas-informaticas-para-el-geoprocesado
Hola muy bueno tus aportes he aprendido mucho,tengo una consulta.
ResponderEliminarEstoy haciendo una funcion en la cual detecta los colores y me dice la cantidad de cada uno.
El problema que tengo que hay imagenes que tengo por ejemplo un rojo y otro casi igual pero me lo pone como colores distintos.
Como puedo simplificar los colores.
Saludos Gracias
Hola jona. Lo que quieres hacer se llama segmentación. Hay muchas formas, unas más fáciles y otras más complejas. Un ejemplo fácil de segmentación es el binarizar una imagen (blanco y negro), o pasarla a escala de grises.
EliminarEspero que te sirva de ayuda.
Un saludo.
Gracias por responder, estoy haciendo una funcion en la cual detecta los colores que hay y me dice la cantidad que tiene de superficie de cada color en una imagen,pero si lo paso a escala de grises,como se a cual color corresponde.
EliminarGracias
Hola muchas gracias por tus aportes, mi problema es que me marca herror en esta parte.
ResponderEliminarPrivate Sub Form1_Load(sender As Object, e As EventArgs) Handles MyBase.Load
Dim bmp As New Bitmap(PictureBox1.Image)
Me dice: No se controló NullReferenceException.