Java eliminar la sombra del documento

Java eliminar la sombra del documento

I. Introducción

Todo el mundo utiliza con frecuencia el escaneo de documentos. Se pueden guardar todo tipo de documentos y documentos en el teléfono móvil a través de la función de escaneo de documentos. En comparación con tomar una fotografía directamente, al escanear un documento, el programa realizará algunas correcciones en la imagen. Como eliminación de sombras, corrección de inclinación, corrección de rotación, etc. Las imágenes posteriores a estos procesos son más fáciles de identificar. Hoy discutiremos las siguientes operaciones para eliminar sombras.

2. Principio de implementación

1. Imagen

Antes de comenzar a implementar, comprendamos algunos conocimientos relacionados con las imágenes. Aquí analizamos las imágenes RGB, que comúnmente se conocen como imágenes en color. La imagen se puede ver como una matriz de alto × ancho, donde cada número representa un píxel. Si es una imagen en color, cada píxel contendrá tres valores de RBG, el byte más bajo representa G, el segundo byte más bajo representa B y el tercer byte representa R.

Imagen 2.png

Por ejemplo, el valor del píxel es:

0x00ff00

Sus valores RBG son:

R: 0x00
G: 0xff
B: 0x00

Si desea obtener el valor RGB del píxel original, puede utilizar la operación bit a bit Y. El ejemplo es el siguiente:

// pixel是从图像中取出来的数
int[] rgb = new int[3];
rgb[0] = (pixel & 0xff0000) >> 16;
rgb[1] = (pixel & 0xff00) >> 8;
rgb[2] = (pixel & 0xff); 

Porque al obtener R y G, los bits altos se retienen. Esperamos obtener datos de bits bajos, así que deslícelos una cierta posición hacia la derecha.

2. Conversión en escala de grises

A veces, las imágenes se convierten a imágenes en escala de grises para facilitar el procesamiento. Hay muchas formas de convertir una imagen en escala de grises. Una forma muy sencilla es hacer que los tres canales de rgb tengan el mismo valor. Este valor es el valor medio de los tres valores de rgb.

3. Procesamiento de umbral

El procesamiento de umbral es una parte clave de la actualidad. La idea del procesamiento de umbral es muy simple, es decir, cuando el valor de píxel de la imagen es mayor que el valor de umbral, se procesa al valor máximo y cuando el valor de píxel es menor. mayor o igual al valor umbral, se procesa a 0. Esto da como resultado una imagen completamente en blanco y negro.

En un documento, el texto se puede ver en negro, el fondo en blanco y la sombra es un valor entre blanco y negro. Si desea eliminar la sombra, debe establecer un umbral en la imagen y establecer el umbral en un valor menor que la sombra. Por ejemplo, la siguiente imagen:

Imagen 4.png

La imagen de la izquierda es la imagen original, en la que la parte gris es la sombra y debe eliminarse. En este momento, realizamos un procesamiento de umbral en la imagen y establecemos el umbral en 50, luego la parte de sombra se establecerá en 255 y la parte de texto y la parte de fondo no cambiarán mucho, logrando así el trabajo de eliminación de sombras de la imagen. manuscrito.

3. Implementación del código

1. Lee la imagen

Primero, echemos un vistazo a cómo leer una imagen y cómo acceder a los píxeles de la imagen, usando la clase ImageIO. El código se muestra a continuación:

import javax.imageio.ImageIO;
import java.awt.image.BufferedImage;
import java.io.File;

public class DocumentDealing {
    
    

    public static void main(String[] args) throws Exception {
    
    
        String imagePath = "D:/images/imgs/10000.jpeg";
        BufferedImage bi = ImageIO.read(new File(imagePath));
        //获取图片宽高
        int width = bi.getWidth();
        int height = bi.getHeight();
        System.out.println("width:" + width + ",height:" + height);
        //获取坐标为(0, 0)位置的像素
        int pixel = bi.getRGB(0, 0);
        System.out.println("pixel" + pixel);
        //获取rgb值
        int[] rgb = new int[3];
        rgb[0] = (pixel & 0xff0000) >> 16;
        rgb[1] = (pixel & 0xff00) >> 8;
        rgb[2] = pixel & 0xff;
        System.out.println(
                "r:" + rgb[0] +
                        "\tg:" + rgb[1] +
                        "\tb:" + rgb[2]
        );
    }

    public static int[] getRgb(BufferedImage bi, int x, int y) {
    
    
        int[] rgb = new int[3];
        int pixel = bi.getRGB(x, y);
        rgb[0] = (pixel & 0xff0000) >> 16;
        rgb[1] = (pixel & 0xff00) >> 8;
        rgb[2] = (pixel & 0xff);
        return rgb;
    }

}

Podemos leer la imagen a través del siguiente código, donde imagePath es la ruta de la imagen:

BufferedImage bi = ImageIO.read(new File(imagePath));

BufferedImage puede obtener el ancho, alto, píxeles de un determinado punto, etc. de la imagen. Por conveniencia, escriba getRgb para convertir píxeles en una matriz rgb. La salida del código es la siguiente:

width:400,height:400
pixel-2853206
r:212	g:118	b:170

2. Procesamiento de umbral

Después de conocer las operaciones básicas anteriores, puede iniciar el procesamiento de umbrales. El umbral es encontrar la media rgb. Si la media es mayor que el umbral, el píxel se establece en 0xffffff; de lo contrario, se establece en 0. El código específico es el siguiente:

import javax.imageio.ImageIO;
import java.awt.image.BufferedImage;
import java.io.File;

public class DocumentDealing {
    
    

    public static void main(String[] args) throws Exception {
    
    
        String imagePath = "C:/Users/Administrator/Desktop/document.jpg";
        threshold(imagePath, "result.jpg", 50);
    }

    public static void threshold(String imagePath, String savePath, int threshold) throws Exception{
    
    
      	//读取图片
        BufferedImage bi = ImageIO.read(new File(imagePath));
        //读取宽高
      	int width = bi.getWidth();
        int height = bi.getHeight();
      	//遍历图片像素
        for(int y = 0; y < height; y ++){
    
    
            for(int x = 0; x < width; x ++){
    
    
                int[] rgb = getRgb(bi, x, y);
              	//计算rgb均值
                int grayScale = (rgb[0] + rgb[1] + rgb[2]) / 3;
              	//如果均值大于阈值,则赋值将该像素设置为0xffffff(全白),否则赋值为0(全黑)
                if(grayScale > threshold){
    
    
                  	bi.setRgb(x, y, 0xffffff);
                }else{
    
    
                  	bi.setRgb(x, y, 0);
                }
            }
        }
      	//保存图片
        ImageIO.write(bi, "jpg", new File(savePath));
    }

    public static int[] getRgb(BufferedImage bi, int x, int y){
    
    
        int[] rgb = new int[3];
        int pixel = bi.getRGB(x, y);
        rgb[0] = (pixel & 0xff0000) >> 16;
        rgb[1] = (pixel & 0xff00) >> 8;
        rgb[2] = (pixel & 0xff);
        return rgb;
    }

}

La siguiente imagen es la imagen original y el resultado procesado:

Imagen 1.png

Hay dos sombras en la imagen de la izquierda y las sombras de la derecha se han eliminado. La imagen del efecto final está relacionada con el umbral establecido. Cuando el umbral no se establece correctamente, la imagen resultante será peor que la imagen original o se eliminará el objeto de texto final. Esto se puede resolver usando un bucle, el código es el siguiente:

public static void main(String[] args) throws Exception {
    
    
	String imagePath = "C:/Users/Administrator/Desktop/document.jpg";
  	for (int i = 50; i < 127; i++) {
    
    
    	threshold(imagePath, "imgs/result" + i + ".jpg", i);
  	}
}

Los lectores pueden probarlo ellos mismos. A veces, el procesamiento de umbral no puede eliminar muy bien las sombras, en este momento se combinarán algunos otros métodos. Incluyendo operaciones de filtrado, procesamiento morfológico, etc. Los lectores interesados ​​pueden obtener más información sobre lo siguiente.

Supongo que te gusta

Origin blog.csdn.net/ZackSock/article/details/128225047
Recomendado
Clasificación