Mostrando entradas con la etiqueta Procesamiento digital de imágenes. Mostrar todas las entradas
Mostrando entradas con la etiqueta Procesamiento digital de imágenes. Mostrar todas las entradas

01 diciembre 2010

Implementación de un cuantizador “midtread” en MATLAB 7.0

La cuantización es el paso necesario para convertir una señal analógica a una digital, cuando se muestrea una señal se convierte del mundo analógico al mundo digital, y es necesario expresarlo en 0s y 1s, dícese bits. Aunque no necesariamente es el proceso de una señal analógica per se, puede ser también, por ejemplo, una imagen que necesita ser representada con una cantidad menor de bits, y por lo consiguiente comprimirla, con pérdidas claro está.

Existen variados tipos de cuantización. El tipo de cuantizador se elige dependiendo de la aplicación en que vaya a ser implementado, esto, de acuerdo a las características de la señal. En este caso se hará un pequeño ejemplo con un cuantizador midtread la grafica siguiente muestra el comportamiento de un cuantizador midtread de 3bits.

cuantización

Figura 1. Características de un cuantizador midtread de 3 bits

El principal uso de este cuantizador es cuando tenemos una señal simétrica en el espectro positivo y negativo, por ejemplo una señal de audio, aunque también se puede aplicar en una imagen, como se muestra en el párrafo siguiente.

En la Figura 1 el eje equis (x) representa la señal a cuantizar y el eje ye (y) es la información ya cuantizada, delta () son los incrementos en los que se va a dividir la señal y esto depende del número de bits que sea el cuantizador, de lo anterior se puede desprender la siguiente tabla:

Código binario Nivel de Cuantización (y) Rango de la señal de entrada (x)

011

-3∆

–3.5∆ <= x < –2.5∆

010

-2∆

–2.5∆ <= x < –1.5∆

001

-1∆

–1.5∆ <= x < –0.5∆

000

0

–0.5∆ <= x < 0

100

0

0 <= x < 0.5∆

101

1∆

0.5∆ <= x < 1.5∆

110

2∆

1.5∆ <= x < 2.5∆

111

3∆

2.5∆ <= x < 3.5∆

La variable delta (∆) puede ser calculada de la siguiente manera

clip_image002

Ora si, vamos a ver el siguiente ejemplo, tenemos la señal de entrada x(n) = 254 254 252 254 255 253 y el rango válido de datos es de 250 a 255, que bien puede ser parte de una imagen ;) .

El primer paso es calcular delta.

clip_image002[4]

Sustituyendo ∆ en la tabla anterior tenemos:

Código binario Nivel de Cuantización (y) Rango de la señal de entrada (x)

011

-3(0.71428) = -2.14284

–2.5 <= x < –1.7857

010

-2(0.71428) = -1.42856

–1.7857 <= x < –1.07142

001

-1(0.71428) = 0.71428

–1.07142 <= x < –0.35714

000

0

–0.35714 <= x < 0

100

0

0 <= x < 0.35714

101

1(0.71428) = 0.71428

0.35714<= x < 1.07142

110

2(0.71428) = 1.42856

1.07142 <= x < 1.7857

111

3(0.71428) = 2.14284

1.7857 <= x < 2.5

Para poder tener los datos de forma como se muestra en la Figura 1, es necesario definir cual es la media de nuestro rango, que en este caso es:

clip_image002[6]

Si restamos a la señal de entrada la media obtenida en el paso anterior tenemos que:

x(n) – µ = 1.5 1.5 -0.5 1.5 2.5 0.5

ahora el siguiente paso es cuantizar cada valor utilizando la tablita arriba descrita…

x(0) = 1.5, cae entre 1.07142 y 1.7857 a lo cual corresponde un valor de cuantización de 1.42856 o sea 110 binario.

x(1) = 1.5, cae entre 1.07142 y 1.7857 a lo cual corresponde un valor de cuantización de 1.42856 o sea 110 binario.

x(2) = –0.5, cae entre –0.35714 y –1.07142 a lo cual corresponde un valor de cuantización de –1.42856 o sea 010 binario.

x(3) = 1.5, cae entre 1.07142 y 1.7857 a lo cual corresponde un valor de cuantización de 1.42856 o sea 110 binario.

x(4) = 2.5, cae entre 1.7857 y 2.5 a lo cual corresponde un valor de cuantización de 2.14284 o sea 111 binario.

x(5) = 0.5 cae entre 0.35714 y 1.07142 a lo cual corresponde un valor de cuantización de 1.42856 o sea 010 binario.

A continuación se presenta el código en MATLAB 7.0 para llevar a cabo esta cuantización:

x = [254 254 252 254 255 253];

bits = 3;
rango_superior = 255;
rango_inferior = 250;

delta = (rango_superior - rango_inferior)/((2^bits)-1)

mu = ((rango_superior - rango_inferior)/2) + rango_inferior

x_centrada = x - mu

x_cuantizada = floor(x_centrada/delta+0.5) * delta

y los resultados son:

delta =

    0.7143

mu =

  252.5000

x_centrada =

    1.5000    1.5000   -0.5000    1.5000    2.5000    0.5000

x_cuantizada =

    1.4286    1.4286   -0.7143    1.4286    2.8571    0.7143

29 noviembre 2010

DPCM (Differential Pulse Code Modulation), Método diferencial para compresión de señales, Parte I, puro rollo

La teoría del siguiente choro mareador y las figuras pirateadas fueron tomad@s de:
Data Compression: The Complete Reference. David Salomon. Fourth Edition. Springer. 2007. Section 4.26: DPCM
Digital Signal Processing: Fundamentals and Applications. Li Tan. Academic Press. 2008. Section 11.3: Examples of Differential Pulse Code Modulation, and Adaptive DPCM G.721

La compresión por DPCM es parte de la familia de métodos compresión por codificación diferencial. La idea general es usar valores pasados recuperados como base para predecir el dato actual de entrada. Esto se basa en el hecho, por ejemplo, que los pixeles en una imagen o muestras adyacentes en el audio digitalizado se encuentran correlacionadas. Los valores correlacionados son generalmente similares, así que sus diferencias son pequeñas, esto resultando en una compresión.
A continuación se muestra el esquema simple de compresión diferencial para poder entender el principio del DPCM.

image

                           Codificador                                 Decodificador
Figura 1. CoDec Diferencial

La imagen anterior muestra un ejemplo de un codificador diferencial, se observa como el dato actual image se almacena en una unidad de almacenamiento, llámese “Delay” (o retardo pues si no les gusta agringarse), para ser usado para codificar el siguiente dato, o sea, image. Claro, la explicación anterior esta sumamente simplificada, en este ejemplo se muestra el uso de un cuantizador, eso significa que se tiene una compresión con perdidas o “lossy” y esto significa que nuestro dato codificado es realmente image el cual ya contiene un error de cuantización. Esto significa que la codificación por diferencias (o diferencial, como ustedes gusten y manden) nos mete en un nuevo problema: La acumulación de errores.
Entonces hay que tomar ventaja de lo que se menciona anteriormente, los datos que se van a comprimir están correlacionados. Esto significa que en general un dato depende de varios de sus vecinos, no solamente del anterior. Una mejor predicción puede ser lograda usando N de los datos previos para codificar el valor actual image, entonces tendremos una función image image, para predecir el dato actual image.
Ora si, en seguida pueden observar (jeje, como visita al museo) el diagrama del DPCM. (oooooohhhh!)

image
                          Codificador                                   Decodificador
Figura 2. DPCM
Oquey, oquey, haber encuentren la(s) diferencia(s) entre la Figura 1 y la Figura 2. ¿Está fácil? ¿que no? …
Pues si, cambiamos “Delay” por “Pred.” y se acabo el asunto.
Si.
Como se explicaba antes, el predictor viene siendo la funcioncica esta:
imageimage
En donde tenemos que es una función que nos afecta un conjunto de N pixeles y en base a esto obtenemos una mejor predicción de nuestro valor actual, es decir tratamos de minimizar el error introducido por la cuantificación.
Esta es la primera parte de dos, en esta ocasión fue el rollo previo a un ejemplo peque para poder explicar la DPCM.

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






28 julio 2009

¿Qué es compresión de Imágenes?

Antes de terminar el compresor (que en estos momentos creo que no va a servir mas que de práctica, je je je, bueno, de todos modos no pensaba desbancar al JPG, todavía), quiero explicar un poco que es la compresión de imágenes. Voy a empezar por poner un par de definiciones:


"La compresión de imágenes aborda el problema de reducir la cantidad de datos para representar una imagen digital. La compresión se logra removiendo una o más de las tres posibles redundancias básicas. (a)Redundancia de código: cuando se usan códigos de palabra menos óptimos (de menor longitud). (b)Redundancia interpixelaria: Que resulta de la correlación entre pixeles de una imagen. (c)Redundancia psicovisual: La cual se da debido a los datos que el sistema de visión humano ignora"1

Según Wikipedia:
"Compresión de imágenes es la aplicación de la compresión de datos en imágenes digitales. En efecto, el objetivo es reducir redundancias en la imagen con el objetivo de transmitirla o almacenarla en una manera eficiente. La compresión puede ser con pérdidas (lossy), o sin pérdidas (lossless). La compresión con pérdidas que produce diferencias imperceptibles se llama también visualmente sin pérdidas (visual lossless)."2

Entonces podemos decir que se trata de reducir el número de bits con necesarios para representar una imagen. Y hay de dos tipos (que pueden ser tres, y no es el chiste del gato). Con pérdidas, sin pérdidas y visualmente sin pérdidas. En el ejemplo de compresor que estoy tratando de hacer, es un compresor con pérdidas, de una imagen en escala de grises de 8 bits.

Pero bueno, ¿cómo le hacemos para saber si el compresor que estamos haciendo vale la pena? Pues fácil, hacemos un montón de pruebas, observamos las imágenes resultantes y la que no se vea tan peor pues decimos que es nuestra imagen codificada usando un compresor con pérdidas. También lo podemos hacer de la manera fancy, usamos PSNR o MSE o cualquier otra medida de error matemática para ver que tanto se distorsiona en referencia con la imagen original.


  1. Digital Image Processing 2nd Edition (DIP/2e)
    by Gonzalez and Woods
    © 2002. Prentice Hall
  2. Image Compression
    From Wikipedia, the free encyclopedia. Extracted July 28th, 2009

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?

28 mayo 2009

Ejemplo simple de una interfaz gráfica usando GUIDE en MATLAB para procesamiento digital de imágenes

Hace poco que aprendí lo básico de crear interfaces gráficas en Matlab. En realidad es hasta cierto punto simple, pero también creo que no es del todo amigable para crear GUIs. Si, estoy de acuerdo que tiene un estilo de editor para hacernos más fácil la existencia. Pero no es del todo intuitivo, o al menos es lo que pienso en el par de programitas que he tenido oportunidad de hacer. Bueno dejando las quejas a un lado, voy a empezar con el ejemplo. Voy a crear una ventana en la que se cargue una imagen por medio de un botón y desplegarla en la ventana, y hacer un procesamiento sencillo y también mostrarlo en pantalla, se que es un ejemplo muy básico, pero creo que es perfecto para empezar. (o al menos es lo que andaba buscando yo cuando quise hacer esto)


Lo primero que tenemos que hacer es iniciar el editor GUIDE que se puede hacer de dos maneras, la primera es desde el menú de inicio: File –> New –> GUI como se muestra en la siguiente imagen.


Guide1


También se puede iniciar desde la línea de comandos o “command window” de Matlab poniendo “guide”.  Aparece una ventana de inicio del GUIDE.


guidestart




La ventana anterior es (como su nombre lo indica) el lanzador rápido para el GUIDE con varias opciones, la que vamos a seleccionar es la que viene por default y presionamos “OK” y nos aparece el editor de interfaces gráficas en blanco, como se muestra a continuación:


Untitled Como primer paso vamos a insertar el objeto que nos va a servir para desplegar la imagen en la ventana. En este caso Matlab lo maneja con “axes”, así que presionamos el botón que esta en la barra de herramientas de la izquierda y ponemos dos “axes” que es donde vamos a cargar la imagen original y la procesada, como se muestra en la siguiente imagen.


ConAxes


Luego presionando el botón “Push Button” (1) ponemos dos botones (2) que el primero nos va a servir para seleccionar el archivo de la imagen y el segundo para procesarla, también vamos a mostrar donde se seleccionan y se cambian las propiedades del objeto (3).


PonerBotones


En la figura siguiente se muestra el inspector de propiedades “property inspector” en donde podemos modificar las propiedades del botón. En el (1)  se modifica el texto del botón, y en (2), se modifica el nombre del botón.


PropertyInspectorModificamos (1) y (2) para cada botón de manera que nos quede como en la imagen siguiente.


Cambios 


En donde dice String simple y sencillamente cambiamos el texto que tiene el botón y en donde dice tag se define el nombre del botón, esto es importante, porque aquí es donde definimos el nombre que va a tener la función Callback” que es la que se manda llamar cuando se presiona el botón. En la imagen siguiente se muestra como queda la GUI con los cambios hechos. Tambien se muestra como tener acceso a la función donde vamos a poner el código que nos cargue la imagen en pantalla.


GuimodificadaA continuación se abre la ventana del editor de códigos de MATLAB y nos selecciona el inicio de la función en la que debemos agregarle nuestro código que en este ejemplo nos va a seleccionar un archivo para ponerlo en axes1. 


CallbackUna vez que tenemos el editor de MATLAB abierto, buscamos el siguiente código y le agregamos la línea de código que se muestra a continuación, lo que se esta haciendo es agregar una variable para almacenar en memoria la imagen que vamos a cargar .


% --- Executes just before GuiBasica is made visible.
function GuiBasica_OpeningFcn(hObject, eventdata, handles, varargin)
% This function has no output args, see OutputFcn.
% hObject    handle to figure
% eventdata  reserved - to be defined in a future version of MATLAB
% handles    structure with handles and user data (see GUIDATA)
% varargin   command line arguments to GuiBasica (see VARARGIN)


% Choose default command line output for GuiBasica
handles.output = hObject;


%Add variable to hold images (Agregar variable para almacenar imágenes)
handles.myImage = [];


% Update handles structure
guidata(hObject, handles);



La línea que agregué en el código anterior es donde dice handles.myImage = []; que nos va a servir para almacenar la imagen temporalmente para procesarla cuando tengamos que hacerlo en el botón que definimos para procesar la imagen.


El código siguiente se agrega en el callback del botón CargarImagen.


% --- Executes on button press in CargarImagen.
function CargarImagen_Callback(hObject, eventdata, handles)
% hObject    handle to CargarImagen (see GCBO)
% eventdata  reserved - to be defined in a future version of MATLAB
% handles    structure with handles and user data (see GUIDATA)
try
    [filename,pathname] = uigetfile('*.pgm','Selecciona imagen para abrir');


    if isequal(filename,0)
        %Do nothing yet
    else
        handles.myImage = imread(fullfile(pathname, filename));


        [X, myMap] = gray2ind(handles.myImage);
        mImagen2 = ind2rgb(X,myMap);


        image(mImagen2, 'Parent', handles.axes1);
        colormap(gray);
    end
    guidata(hObject, handles);
catch
    msgbox('Error')
end



Y agregando el código siguiente al callback del botón ProcesarImagen como se muestra a continuación hacemos nuestro ejemplo de procesamiento, aquí solamente voy a hacer el negativo de la imagen para ilustrar el ejemplo con algo simple, en este caso se pretende mostrar como hacer un GUI en MATLAB, no dar una clase de procesamiento de imágenes.


% --- Executes on button press in ProcesarImagen.
function ProcesarImagen_Callback(hObject, eventdata, handles)
% hObject    handle to ProcesarImagen (see GCBO)
% eventdata  reserved - to be defined in a future version of MATLAB
% handles    structure with handles and user data (see GUIDATA)
    guidata(hObject, handles);
    mImage = handles.myImage;   
    mImage2 = 255-mImage;
    [X, myMap] = gray2ind(mImage2);
    mImagen2 = ind2rgb(X,myMap);


    image(mImagen2, 'Parent', handles.axes2);



Y a continuación se muestra como queda el resultado final de nuestra GUI.


Resultado Si todo se ha hecho como se indica, debería de funcionar. jeje. En caso de que me falte un paso o que algo no se entienda solo manden un correo y trataré de corregirlo. gustavo.ramirez.v@gmail.com

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.