¿Cuáles son los mejores algoritmos para el umbral de la imagen del documento en este ejemplo?

31

Estoy tratando de implementar varios algoritmos de binarización en la imagen que se muestra: ingrese la descripción de la imagen aquí

Aquí está el código:

clc;
clear;
x=imread('n2.jpg');     %load original image

% Ahora redimensionamos las imágenes para que el trabajo computacional sea más fácil para nosotros más adelante.

size(x);
x=imresize(x,[500 800]);
figure;
imshow(x);
title('original image');

z=rgb2hsv(x);       %extract the value part of hsv plane
v=z(:,:,3);
v=imadjust(v);

% ahora encontramos la media y la desviación estándar requerida para los algoritmos niblack y% sauvola

m = mean(v(:))
s=std(v(:))
k=-.4;
value=m+ k*s;
temp=v;

% de implementación del algoritmo de umbral niblack:

for p=1:1:500
    for q=1:1:800
        pixel=temp(p,q);
        if(pixel>value)
            temp(p,q)=1;
        else
            temp(p,q)=0;
        end
    end
end
figure;
imshow(temp);
title('result by niblack');
k=kittlerMet(g);
figure;
imshow(k);
title('result by kittlerMet');

% de implementación del algoritmo de umbral de Sauvola:

val2=m*(1+.1*((s/128)-1));
t2=v;
for p=1:1:500
for q=1:1:800
    pixel=t2(p,q);
    if(pixel>value)
        t2(p,q)=1;
    else
        t2(p,q)=0;
    end
end

fin

figure;
imshow(t2);
title('result by sauvola');

Los resultados que obtuve son los que se muestran: ingrese la descripción de la imagen aquí ingrese la descripción de la imagen aquí ingrese la descripción de la imagen aquí

Como puede ver, las imágenes resultantes se degradan en los puntos más oscuros. ¿Podría alguien sugerirme cómo optimizar mi resultado?

marca
fuente
1
¿Se puede usar la información de color para desechar el fondo en lugar de solo el brillo?
endolito el
Respetado señor / señora. Estoy haciendo un proyecto de procesamiento de imágenes. Soy un concepto interesante de binarización ... compruebe y corrija la codificación ... Tomo la codificación y ejecuto el programa. Pero se produce algún error en esta codificación ... Función indefinida o variable 'g'. y otro es Error en msp (línea 31) k = kittlerMet (g); .. Cómo resolverlo ... Corrija la codificación ...
muthu

Respuestas:

49

Su imagen no tiene brillo uniforme, por lo que no debe trabajar con un umbral uniforme. Necesitas un umbral adaptativo. Esto se puede implementar preprocesando la imagen para hacer que el brillo sea más uniforme en toda la imagen (código escrito en Mathematica, deberá implementar la versión de Matlab por usted mismo):

Una manera simple de hacer que el brillo sea uniforme es eliminar el texto real de la imagen usando un filtro de cierre:

white = Closing[src, DiskMatrix[5]]

ingrese la descripción de la imagen aquí

El tamaño del filtro debe elegirse más grande que el ancho del trazo de la fuente y más pequeño que el tamaño de las manchas que está tratando de eliminar.

EDITAR: En los comentarios me pidieron que explicara qué hace una operación de cierre. Es una dilatación morfológica seguida de una erosión morfológica . La dilatación esencialmente mueve el elemento estructurante en cada posición de la imagen y selecciona el píxel más brillante debajo de la máscara, por lo tanto:

  • eliminar estructuras oscuras más pequeñas que el elemento estructurante
  • reducir las estructuras oscuras más grandes por el tamaño del elemento estructurante
  • agrandar estructuras brillantes

La operación de erosión hace lo opuesto (selecciona el píxel más oscuro debajo del elemento estructurante), por lo que si lo aplica en la imagen dilatada:

  • las estructuras oscuras que se eliminaron porque son más pequeñas que el elemento estructurante aún se han ido
  • Las estructuras más oscuras que se redujeron se amplían nuevamente a su tamaño original (aunque su forma será más suave)
  • las estructuras brillantes se reducen a su tamaño original

Por lo tanto, la operación de cierre elimina pequeños objetos oscuros con solo cambios menores en objetos oscuros más grandes y objetos brillantes.

Aquí hay un ejemplo con diferentes tamaños de elementos estructurantes:

ingrese la descripción de la imagen aquí

A medida que aumenta el tamaño del elemento estructurante, se eliminan más y más caracteres. En radio = 5, se eliminan todos los caracteres. Si el radio aumenta aún más, también se eliminan las manchas más pequeñas:

ingrese la descripción de la imagen aquí

Ahora solo divide la imagen original por esta "imagen blanca" para obtener una imagen de brillo (casi) uniforme:

whiteAdjusted = Image[ImageData[src]/ImageData[white]*0.85]

ingrese la descripción de la imagen aquí

Esta imagen ahora se puede binarizar con un umbral constante:

Binarize[whiteAdjusted , 0.6]

ingrese la descripción de la imagen aquí

Niki Estner
fuente
55
¡Guauu! ¡Esto es realmente genial! Enorme +1!
Phonon
@nikie +1 Muy bien, ¿qué quieres decir exactamente con el cierre del filtro debe ser "elegido más grande que el trazo de fuente"? Ancho o largo de cualquier letra? Además, ¿qué está haciendo un filtro de cierre "realmente"? ¡Gracias!
Spacey
1
@Mohammad: He agregado una pequeña explicación a mi respuesta. Y sí, estas son operaciones no lineales. El encabezado común es el procesamiento de imágenes morfológicas.
Niki Estner
1
@nikie No importa, el blanco es el máximo, no el negro. :-)
Spacey
1
@gdelfino: Por lo general, trato de evitarlo usando una máscara lo suficientemente grande, y uso Clip[ImageData[white],{eps,Infinity}]donde eps es un número pequeño, para estar seguro.
Niki Estner
6

La respuesta de Nikie parece la mejor y también parece estar funcionando y produciendo resultados. Entonces es un claro ganador.

Sin embargo, solo a la documentación agrego una referencia más, eso podría ser muy rápido.

Esta técnica se llama umbral adaptable que no requiere aprender el fondo explícitamente.

Esencialmente, en lugar de encontrar el umbral global más adecuado , podemos particionar la imagen en una ventana local (digamos aproximadamente 7x7 o apropiado) y encontrar umbrales que cambian a medida que la ventana se desplaza.

La referencia a continuación detalla el método exacto. http://homepages.inf.ed.ac.uk/rbf/HIPR2/adpthrsh.htm

Este método sería relativamente más rápido computacionalmente.

Dipan Mehta
fuente
¿No son esas dos cosas esencialmente iguales? A saber, ¿estimar la media local de la señal antes del umbral?
Maurits
1
@Maurits Parece que las principales diferencias son los pedidos y las estadísticas utilizadas. Por ejemplo, en los operadores de apertura / cierre (que están formados por dilatación y erosión pero en un orden diferente), se escanea una ventana y se toma el máximo. (Entre otras cosas). Sin embargo, en el umbral adaptativo se puede tomar la media / mediana en lugar del máximo.
Spacey
OP también lo preguntó en SO , a lo que respondí. Pero, en principio, no creo que haya ninguna diferencia entre las respuestas, siempre se calculan las estadísticas locales. Si realiza un umbral adaptativo, también aprenderá los antecedentes del proceso.
Maurits
6

Otra forma de usar un filtro de paso de banda (en MATLAB). Jugar con la diferencia de los parámetros gaussianos puede dar mejores resultados. El proceso consiste básicamente en filtrar la imagen para eliminar los blobs de fondo de baja frecuencia, normalizar a [0,1] requerido para el comando 'graythresh', imagen umbral.

Cargar imagen y convertir a escala de grises doble:

I = imread('hw.jpg');
I = rgb2gray(I);
I = double(I);

ingrese la descripción de la imagen aquí

Filtrar utilizando la diferencia del núcleo gaussiano y normalizar:

J = imgaussian(I,1.5) - imgaussian(I,0.5);
J = J - min(J(:));
J = J / max(J(:));

ingrese la descripción de la imagen aquí

Calcular el umbral y hacer 010101:

T = J > graythresh(J);

ingrese la descripción de la imagen aquí

Geometrikal
fuente
4

Este es un buen código de Matlab para umbrales adaptativos: http://www.mathworks.com/matlabcentral/fileexchange/8647-local-adaptive-thresholding

MyCarta
fuente
Argh! Sin embargo, requiere la caja de herramientas de procesamiento de imágenes. : - /
Spacey
En efecto. Lo siento si no lo tienes. Pero DIPImage es un Tolbox de imagen gratuito para Matlab. diplib.org/documentation Tiene algunos métodos para umbralizar (ver sección de segmentación) y también puede hacer todas las operaciones morfológicas como cerrar. El desarrollador también tiene un blog cb.uu.se/~cris/blog/index.php/archives/tag/matlab
MyCarta
0

Intentaré esta codificación, pero no tengo una respuesta correcta ...

clc;
clear;
x=imread('base2.jpg');
size(x);
x=imresize(x,[500 800]);
figure;
imshow(x);
title('original image');
z=rgb2hsv(x);       %extract the value part of hsv plane
v=z(:,:,3);
v=imadjust(v);
m = mean(v(:))
s=std(v(:))
k=-2;
value=m+ k*s;
temp=v;
for p=1:1:500
    for q=1:1:800
        pixel=temp(p,q);
        if(pixel>value)
            temp(p,q)=1;
        else
            temp(p,q)=0;
        end
    end
end
figure;
imshow(temp);
title('result by niblack');
% k=kittlerMet(g);
% figure;
% imshow(k);
% title('result by kittlerMet');

val2=m*(1+.1*((s/128)-1));
t2=v;
for p=1:1:500
for q=1:1:800
    pixel=t2(p,q);
    if(pixel>value)
        t2(p,q)=1;
    else
        t2(p,q)=0;
    end
end

end
figure;
imshow(t2);
title('result by sauvola');

ingrese la descripción de la imagen aquí

ingrese la descripción de la imagen aquí

muthu
fuente
2
Si esto está destinado a responder la pregunta, explique qué está haciendo y por qué.
Matt L.