Mostrando entradas con la etiqueta PGM. Mostrar todas las entradas
Mostrando entradas con la etiqueta PGM. Mostrar todas las entradas

05 agosto 2009

Ejemplo para leer una imagen PGM en Visual Basic 6.0

En el mundo de los programadores de software, Visual Basic no sirve para nada, je je, y para un par de cosas es cierto, pero para el resto, no. Déjenme explicarme un poco en esto. Visual Basic es un lenguaje desarrollado para hacer aplicaciones rápidas, en pocas palabras es un RAD (Rapid Application Development) como a los geeks de IBM los 80's les gusto llamarle.

Así que por ende, debe tener unas cosas por otras, es un lenguaje hasta cierto punto fácil de aprender y puedes desarrollar interfaces graficas de tres patadas, pero, pierdes un poco de control sobre la programación así que nada en cuestiones como programación orientada a objetos y apuntadores), conste no es solo esto, si no una lista que desconozco y tampoco necesito conocer. Otra de las desventajas es la lentitud para ejecutar los programas. Esta última es muy notable si lo comparamos con lenguajes un tanto más específicos para el procesamiento digital de imágenes, como por ejemplo MATLAB, o hasta LabVIEW.

Dejando de lado un poco el rollo, este ejemplo lo iniciaremos haciendo la interfaz gráfica de nuestro ejemplito, en una forma de Visual Basic, no iniciaré desde la creación del proyecto para no volver este post muy largo como el ejemplo de GUIDE. Primero ponemos un PictureBox y un CommandButton, el primero lo dejé con el nombre que le pone por default VB Picture1 y el segundo le puse cmdLoadPGM y le cambié el caption a “Cargar PGM”

GUI

La siguiente función es la que se encarga de leer el archivo PGM de la PC, y lo despliega en el Picturebox que le pasamos como parámetro:

Public Function LoadPGMtoPictureBox(strPGMpath As String, myPictureBox As PictureBox)

Dim bytes() As Byte
Dim pFileLenght As Long
Dim iWidth As Long
Dim iHeight As Long
Dim i As Long
Dim j As Long
Dim iCountZeros As Long
Dim iCounter As Long
Dim strCatchWidth As String
Dim strCatchHeight As String
Dim pFileLength As Long
Dim ptrToBytes As Long
Const PGM_MAGIC_NUMBER = "P5"
Dim u As Long
Dim u2 As Long

pFileLength = FileLen(strPGMpath)

ReDim bytes(1 To pFileLength)

Open strPGMpath For Binary Access Read As #10

Get #10, 1, bytes

Close #10

If Not Chr(bytes(1)) & Chr(bytes(2)) = PGM_MAGIC_NUMBER Then _

Exit Function

iCountZeros = 0
iCounter = 4
strCatchWidth = ""
strCatchHeight = ""

Do
strCatchWidth = strCatchWidth & Chr(bytes(iCounter))
iCounter = iCounter + 1
Loop While IsNumeric(Chr(bytes(iCounter)))

Do
strCatchHeight = strCatchHeight & Chr(bytes(iCounter))
iCounter = iCounter + 1
Loop While IsNumeric(Chr(bytes(iCounter)))


iWidth = CInt(strCatchWidth)
iHeight = CInt(strCatchHeight)

For i = 0 To iHeight - 1
For j = 0 To iWidth - 1
ptrToBytes = ((i) * iWidth) + j
u = bytes(ptrToBytes + &H10)
u2 = RGB(u, u, u)
SetPixelV myPictureBox.hdc, j, i, u2
Next j
Next i

myPictureBox.ScaleMode = 3
myPictureBox.Height = iHeight
myPictureBox.Width = iWidth

End Function






27 julio 2009

Update del Compresor que estoy haciendo

  • Ya tengo el algoritmo para hacer la extracción de Bits.
  • Ya tengo el código para codificar la imagen binaria en RLE (gracias JMG, ya lo tenía arrinconado)
  • Ya tengo el código para decodificar la imagen codificada con lo anterior

Ahora solo me falta hacer pruebas suficientes para llegar a una conclusión.

Lo voy a terminar...

... algún día.

16 julio 2009

Idea para un compresor de imágenes con pérdidas usando extracción de bits y codificación RLE a una imagen PGM

Tengo una idea para hacer un compresor de imágenes PGM (por si se preguntan, no, no tengo fijación alguna con este tipo de imágenes solo que es sencillo, ¡gulp!, trabajar con ellas) con pérdidas usando la extracción de bits (medio explicada aquí) y codificación RLE. La idea principal viene de el hecho de que al aplicar un algoritmo extracción de bits a una imagen tenemos un arreglo binario como resultado, tendremos 1 arreglo 2D de ceros y unos por cada bit extraído, es decir que para una imagen de 8-bits, tendremos 8 arreglos de binarios. De esto podemos observar que cada imagen resultante contiene información de la imagen, y se puede observar una degradación empezando del bit más significativo hacia abajo. Se pueden emplear un par de estas imágenes para codificarlas usando un algoritmo de RLE aprovechando que tendremos secuencias de unos y ceros; luego al recuperarlas y aplicarles algún tipo de técnica de Diethering, para mejorar la calidad de la imagen resultante, claro, con pérdida de información con respecto a la original.

A continuación listo los pasos que creo que son necesarios para este algoritmo:

  • Aplicar la extracción de bits a la imagen. Resultado: 8 imágenes (1 por bit en este caso)
  • Seleccionar las imágenes que serán empleadas para la codificación RLE. Resultado: conjunto de imágenes a comprimir.
  • Aplicar RLE a un cada una de las imágenes seleccionadas en el paso anterior. Resultado: n número de conjuntos de datos (1 por imagen). El total de datos obtenidos aquí nos dará como resultado una compresión.
  • Para descomprimir la imagen, aplicamos RLE inversa a los conjuntos de datos. Resultado: n número de imágenes binarias.
  • Se combinan las imágenes obtenidas en el paso anterior (esto es posible asignando cada bit y reconstruyendo la imagen de 8bits). Resultado: Imagen de 8bits con pérdida de información.
  • A la imagen resultante le aplicamos algún tipo de Diethering para mejorar la calidad. Resultado imagen codificada y decodificada con pérdidas.

No se hasta que punto sea posible obtener una buena imagen como resultado, o que tan buena compresión se pueda lograr para mantener un balance entre calidad de imagen y compresión.

Ya pondré los resultados en un post en cuanto tenga algo que valga la pena. :)

11 junio 2009

Ejemplo para cargar una imagen PGM en LabVIEW sin IMAQ

¡También LabVIEW puede Procesar Imágenes!

Je je, antes de que alguien del cuerpo técnico y ventas de National Instruments lea esto, mejor rectifico.

Dado a la naturaleza de LabVIEW también se pueden implementar un par de algoritmos (ja ja, de acuerdo, el universo de posibilidades es infinito, “the sky is the limit”) de la manera en que se haría con MATLAB (según un ingeniero de campo de NI me platicó que al principio eran una sola compañía lo que ahora es Mathworks y NI, pero en algún punto en el tiempo se separaron, así que se disputan el origen del engine de matrices ambos, claro que el inge de NI juraba que era de ellos, jeje, me imagino que dirían los de Mathworks) , ya saben el paradigma orientado a datos que manejan estos de National Instruments, claro ellos tienen un Toolkit dedicado al procesamiento de imágenes, pero este post se enfocará en implementarlo sin el uso del tan famoso Vision Development Module.

Como ya he puesto en otros posts vamos a leer imágenes PGM ya que LabVIEW no cuenta con una librería para leer este tipo de imágenes. Las imágenes PGM son ampliamente usadas para probar algoritmos de procesamiento digital de imágenes,  son fotos en escala de grises cada byte representa un pixel, es decir 8 bits, 256 posibles escalas de grises.

El ejemplo que propongo consta de un VI (instrumento virtual) principal y 3 subVIs. (Los VIs se pueden ver como la contraparte de las funciones en los programas por texto). La primera parte consta de leer un archivo del disco duro, se lee como archivo binario, como resultado de este se obtiene un arreglo de bytes que contiene los valores leídos en el archivo. En seguida pasa por un parser para el encabezado del archivo PGM, que básicamente comienza con dos bytes en ascii representando “P5”, en seguida viene el ancho, seguido del alto de la imagen, y para finalizar el nivel de grises en que está codificada la imagen. En medio de estos debe de estar como separador un espacio, ya sea un espacio en blanco (0x20), un carrier return (0x0D), un line feed (0x0A) o un tab (0x09). También hay que notar que después del “P5” se pueden tener comentarios y se identifican con el símbolo (#) al principio de la línea. Para más información del formato PGM, favor de ir a la página de la especificación.

A continuación se muestra el VI principal que realiza el leer el archivo, procesar la información y mostrarla en pantalla.

ReadPGM_CaseTrue

 

ReadPGM_CaseFalse

 

Una de las funciones del VI “ParsePGMHeader.vi” es determinar si es un archivo válido, es por eso que la salida del VI se alambra a un case para determinar si es válido y continuar o de lo contrario terminar el programa, como se observa en las figuras anteriores. Tengo que agradecer a un miembro del foro de NI (JB) de donde tome el VI para mostrar un msgbox en LabVIEW si lo necesitan pueden checar el foro. (n.d.r: el post es algo viejo y es para una versión de LabVIEW algo vieja por ende, y no se si la versión 8.6 ya tenga algo embebido). A continuación se muestra el diagrama a bloques de “ParsePGMHeader.vi”

ParsePGMHeader

Este parser lo que hace es que lee el bufer de bytes que se leen de el archivo y busca el encabezado, de ahí saca el ancho y el alto de la imagen, (tengo que confesar que este algoritmo no cumple completamente con la especificación, ya que asume que la imagen es de 256 niveles de grises, pero eso no es necesariamente cierto según la especificación; y entonces los pixeles ya no serían necesariamente de un byte, sino de dos. :S) Así como también, determina si es un archivo válido. En seguida lee el valor isPGM? y se mete a un case, para determinar si se continúa con la ejecución o se detiene le programa.

En caso de ser verdadero, se agarra el buffer de datos y se obtiene el buffer de la imagen, como datos de entrada se tiene la salida del VI anterior, el cual le pasa el buffer, en donde empieza la imagen y el ancho y alto de la misma. La salida de este VI nos da un arreglo en 2D conteniendo la imagen. A continuacion se muestra el diagrama del VI “GetPGMImageData.vi”.

GetPGMImageData La salida de este VI se usa para dibujar la imagen PGM en un objeto picture. También da como salida el ancho y alto de la imagen. En seguida se muestra el “DrawPGMImage.vi”. A la cual se le pasa como entrada el arreglo en 2D conteniendo la imagen y a la salida se le conecta  un objeto picture. El diagrama se muestra a continuación.

 

DrawPGMImage 

Al final en el VI se agrega un nodo de propiedades para poder modificar el ancho y alto de la imagen a mostrar, dependiendo del tamaño de la imagen original.

Como decía al principio, es que se trata de cargar la imagen sin necesidad de tener el Toolkit de procesamiento de imágenes, ya que trae integradas funciones para leer archivos png, jpg y bmp, pero no los pgm. Igual, si quieren los archivos para hacer pruebas solo mándenme un email y se los envío con gusto. Todavía ando viendo como hacerle para poder subir archivos y linkearlos al blog, creo que no me va a quedar de otra que usar un disco virtual.

Simple, ¿no?

23 abril 2009

Ejemplo de extracción de bits de una imagen en escala de grises de 8 bits en MATLAB

En este caso supongamos que tenemos una imagen en formato PGM, (escala de grises de 256 niveles, o sea 8 bits). Si queremos extraer la información de cada bit entonces tenemos lo siguiente:

  • u, es el valor del pixel al que le vamos a extraer el bit
  • B, es el número de bits usado para representar un pixel
  • n, es el bit que queremos extraer de cada pixel, B es el menos significativo y 1 es el más significativo
  • L, es en nivel máximo que puede tener nuestra imagen

Según Anil K. Jain en su libro Fundamentals of Digital Image Processing, en el capítulo dedicado al mejoramiento de imágenes (o image enhancement), explica la extracción de bits en una imagen y define al pixel u de la siguiente manera: 

u, nuestro pixel original

y queremos que nuestro pixel resultado v de la extracción de bit sea:

v

El autor define kn como se muestra a continuación: kn

En donde:

in

En  este caso u puede tomar valores entre 0 y 255 (ya que es una imagen PGM de 8 bits). Por ejemplo si decimos que u = 237 y queremos extraer el bit más significativo entonces tenemos que n = 8  y B = 8. Representando u en su equivalente binario tendriamos que u = 11101101. Nos quedaría de la siguiente manera:

    1. in = i8 = int[237/(2^8-8)] = 237
    2. in-1 = i7 = int[237/(2^8-7)] = int[237/2^1] = int[237/2] = int[118.5] = 118
    3. kn = k8 = 237 – 2*118 = 237 – 236 = 1

Enseguida se muestra el codigo en MATLAB para llevar a cabo la extracción de bits de la imagen del bote:

clc;clear;
myImagen = imread('boat.pgm');
myImagenNueva = myImagen;
[rows cols] = size(myImagen);

B = 8;
L = 255;

for n = 1:B
    for i = 1 : rows
        for j = 1 : cols 
            u = double(myImagen(i,j));
            iEne = floor(u/2^(B-n));
            iEneMenosUno = floor(u/2^(B-(n-1)));
            BitExtraido = iEne - (2*iEneMenosUno);
            if BitExtraido == 1
                BitExtraido = L;
            else
                BitExtraido = 0;
            end
            myImagenNueva(i,j) = BitExtraido;
        end
    end
    subplot(2,4,n);
    imshow(myImagenNueva);
    title(['Bit', num2str(n)]);
end



EjemploExtracionDeBitsMATLAB

This is I

Blog dedicado a escribir sobre Sistemas Embebidos y el Internet de las Cosas o IoT que le llaman.