Tess4j Java OCR在我的项目中的应用

一、开发环境

        SpringMvc+Mybatis的Maven项目,Mac OS 环境,IntelliJ IDEA开发工具,本地已经安装ocr

二、环境配置

        1.添加maven依赖库:

        <dependency>
			<groupId>net.sourceforge.tess4j</groupId>
			<artifactId>tess4j</artifactId>
			<version>3.2.1</version>
		</dependency>
		<dependency>
			<groupId>net.java.dev.jna</groupId>
			<artifactId>jna</artifactId>
			<version>4.1.0</version>
		</dependency>
		<dependency>
			<groupId>com.github.jai-imageio</groupId>
			<artifactId>jai-imageio-core</artifactId>
			<version>1.3.1</version>
		</dependency>
		<dependency>
			<groupId>org.ghost4j</groupId>
			<artifactId>ghost4j</artifactId>
			<version>1.0.1</version>
		</dependency>
		<dependency>
			<groupId>commons-io</groupId>
			<artifactId>commons-io</artifactId>
			<version>2.5</version>
		</dependency>
		<dependency>
			<groupId>net.sourceforge.lept4j</groupId>
			<artifactId>lept4j</artifactId>
			<version>1.2.3</version>
		</dependency>
		<!-- Logging Dependencies -->
		<dependency>
			<groupId>ch.qos.logback</groupId>
			<artifactId>logback-classic</artifactId>
			<version>1.1.7</version>
		</dependency>
		<!-- Logging Bridges -->
		<dependency>
			<groupId>org.slf4j</groupId>
			<artifactId>jul-to-slf4j</artifactId>
			<version>1.7.21</version>
		</dependency>
		<dependency>
			<groupId>org.slf4j</groupId>
			<artifactId>jcl-over-slf4j</artifactId>
			<version>1.7.21</version>
		</dependency>
		<dependency>
			<groupId>org.slf4j</groupId>
			<artifactId>log4j-over-slf4j</artifactId>
			<version>1.7.21</version>
		</dependency>

        2.将源码中的部分文件导入到项目中

         将源码 tess4j/src/main/resources 路径下的lib、tessdata、win32-x86-64、win32-x86添加到我的项目的resources目录下,其中tessdata是字库文件,win32-x86-64、win32-x86存放的是windows库文件(.dll),此处导入windows库文件是方便开发包后期在windows平台部署。

            (ps:代码自定义字库路径时指定正确即可,所以此处可放到随意合适位置即可)

        3.拷贝部分源码里的Test代码及代码里边用到的图片文件,运行测试,解析成功则集成完成!此时心里爽爽哒~ 欧耶\(^o^)/

三、代码简单实现

        要更好的完成图像识别,首先需要对图片进行处理,以提高识别率。网上找的两个工具类(时间长了忘了在哪儿找的,如有版权问题请及时与我联系,谢谢!),直接上代码:

        ImageFilter.java

package com.....common.utils.ocr;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import java.awt.*;
import java.awt.color.ColorSpace;
import java.awt.geom.AffineTransform;
import java.awt.image.*;

/**
 *
 * 图像过滤,增强OCR识别成功率
 *
 */
public class ImageFilter {
    protected transient final Logger logger = LoggerFactory.getLogger(this.getClass());
    private BufferedImage image;
    private int iw, ih;
    private int[] pixels;

    public ImageFilter(BufferedImage image) {
        this.image = image;
        iw = image.getWidth();
        ih = image.getHeight();
        pixels = new int[iw * ih];
    }

    /** 图像二值化 */
    public BufferedImage changeGrey() {
        PixelGrabber pg = new PixelGrabber(image.getSource(), 0, 0, iw, ih, pixels, 0, iw);
        try {
            pg.grabPixels();
        } catch (InterruptedException e) {
            logger.error("异常:", e);
        }
        // 设定二值化的域值,默认值为100
        int grey = 100;
        // 对图像进行二值化处理,Alpha值保持不变
        ColorModel cm = ColorModel.getRGBdefault();
        for (int i = 0; i < iw * ih; i++) {
            int red, green, blue;
            int alpha = cm.getAlpha(pixels[i]);
            if (cm.getRed(pixels[i]) > grey) {
                red = 255;
            } else {
                red = 0;
            }

            if (cm.getGreen(pixels[i]) > grey) {
                green = 255;
            } else {
                green = 0;
            }

            if (cm.getBlue(pixels[i]) > grey) {
                blue = 255;
            } else {
                blue = 0;
            }

            pixels[i] = alpha << 24 | red << 16 | green << 8 | blue;
        }
        // 将数组中的象素产生一个图像
        return ImageIOHelper.imageProducerToBufferedImage(new MemoryImageSource(iw, ih, pixels, 0, iw));
    }

    /** 提升清晰度,进行锐化 */
    public BufferedImage sharp() {
        PixelGrabber pg = new PixelGrabber(image.getSource(), 0, 0, iw, ih, pixels, 0, iw);
        try {
            pg.grabPixels();
        } catch (InterruptedException e) {
            logger.error("异常:", e);
        }

        // 象素的中间变量
        int tempPixels[] = new int[iw * ih];
        for (int i = 0; i < iw * ih; i++) {
            tempPixels[i] = pixels[i];
        }
        // 对图像进行尖锐化处理,Alpha值保持不变
        ColorModel cm = ColorModel.getRGBdefault();
        for (int i = 1; i < ih - 1; i++) {
            for (int j = 1; j < iw - 1; j++) {
                int alpha = cm.getAlpha(pixels[i * iw + j]);
                // 对图像进行尖锐化
                int red6 = cm.getRed(pixels[i * iw + j + 1]);
                int red5 = cm.getRed(pixels[i * iw + j]);
                int red8 = cm.getRed(pixels[(i + 1) * iw + j]);
                int sharpRed = Math.abs(red6 - red5) + Math.abs(red8 - red5);

                int green5 = cm.getGreen(pixels[i * iw + j]);
                int green6 = cm.getGreen(pixels[i * iw + j + 1]);
                int green8 = cm.getGreen(pixels[(i + 1) * iw + j]);
                int sharpGreen = Math.abs(green6 - green5) + Math.abs(green8 - green5);

                int blue5 = cm.getBlue(pixels[i * iw + j]);
                int blue6 = cm.getBlue(pixels[i * iw + j + 1]);
                int blue8 = cm.getBlue(pixels[(i + 1) * iw + j]);
                int sharpBlue = Math.abs(blue6 - blue5) + Math.abs(blue8 - blue5);

                if (sharpRed > 255) {
                    sharpRed = 255;
                }
                if (sharpGreen > 255) {
                    sharpGreen = 255;
                }
                if (sharpBlue > 255) {
                    sharpBlue = 255;

                }
                tempPixels[i * iw + j] = alpha << 24 | sharpRed << 16 | sharpGreen <<8 | sharpBlue;
            }
        }
        // 将数组中的象素产生一个图像
        return ImageIOHelper.imageProducerToBufferedImage(new MemoryImageSource(iw, ih,tempPixels, 0, iw));
    }

    /** 中值滤波 */
    public BufferedImage median() {
        PixelGrabber pg = new PixelGrabber(image.getSource(), 0, 0, iw, ih, pixels, 0, iw);
        try {
            pg.grabPixels();
        } catch (InterruptedException e) {
            logger.error("异常:", e);
        }
        // 对图像进行中值滤波,Alpha值保持不变
        ColorModel cm = ColorModel.getRGBdefault();
        for (int i = 1; i < ih - 1; i++) {
            for (int j = 1; j < iw - 1; j++) {
                int red, green, blue;
                int alpha = cm.getAlpha(pixels[i * iw + j]);
                // int red2 = cm.getRed(pixels[(i - 1) * iw + j]);
                int red4 = cm.getRed(pixels[i * iw + j - 1]);
                int red5 = cm.getRed(pixels[i * iw + j]);
                int red6 = cm.getRed(pixels[i * iw + j + 1]);
                // int red8 = cm.getRed(pixels[(i + 1) * iw + j]);

                // 水平方向进行中值滤波
                if (red4 >= red5) {
                    if (red5 >= red6) {
                        red = red5;
                    } else {
                        if (red4 >= red6) {
                            red = red6;
                        } else {
                            red = red4;
                        }
                    }
                } else {
                    if (red4 > red6) {
                        red = red4;
                    } else {
                        if (red5 > red6) {
                            red = red6;
                        } else {
                            red = red5;
                        }
                    }
                }

                // int green2 = cm.getGreen(pixels[(i - 1) * iw + j]);
                int green4 = cm.getGreen(pixels[i * iw + j - 1]);
                int green5 = cm.getGreen(pixels[i * iw + j]);
                int green6 = cm.getGreen(pixels[i * iw + j + 1]);
                // int green8 = cm.getGreen(pixels[(i + 1) * iw + j]);

                // 水平方向进行中值滤波
                if (green4 >= green5) {
                    if (green5 >= green6) {
                        green = green5;
                    } else {
                        if (green4 >= green6) {
                            green = green6;
                        } else {
                            green = green4;
                        }
                    }
                } else {
                    if (green4 > green6) {
                        green = green4;
                    } else {
                        if (green5 > green6) {
                            green = green6;
                        } else {
                            green = green5;
                        }
                    }
                }

                // int blue2 = cm.getBlue(pixels[(i - 1) * iw + j]);
                int blue4 = cm.getBlue(pixels[i * iw + j - 1]);
                int blue5 = cm.getBlue(pixels[i * iw + j]);
                int blue6 = cm.getBlue(pixels[i * iw + j + 1]);
                // int blue8 = cm.getBlue(pixels[(i + 1) * iw + j]);

                // 水平方向进行中值滤波
                if (blue4 >= blue5) {
                    if (blue5 >= blue6) {
                        blue = blue5;
                    } else {
                        if (blue4 >= blue6) {
                            blue = blue6;
                        } else {
                            blue = blue4;
                        }
                    }
                } else {
                    if (blue4 > blue6) {
                        blue = blue4;
                    } else {
                        if (blue5 > blue6) {
                            blue = blue6;
                        } else {
                            blue = blue5;
                        }
                    }
                }
                pixels[i * iw + j] = alpha << 24 | red << 16 | green << 8 | blue;
            }
        }
        // 将数组中的象素产生一个图像
        return ImageIOHelper.imageProducerToBufferedImage(new MemoryImageSource(iw, ih,pixels, 0, iw));
    }

    /** 线性灰度变换 */
    public BufferedImage lineGrey() {
        PixelGrabber pg = new PixelGrabber(image.getSource(), 0, 0, iw, ih, pixels, 0, iw);
        try {
            pg.grabPixels();
        } catch (InterruptedException e) {
            logger.error("异常:", e);
        }
        // 对图像进行进行线性拉伸,Alpha值保持不变
        ColorModel cm = ColorModel.getRGBdefault();
        for (int i = 0; i < iw * ih; i++) {
            int alpha = cm.getAlpha(pixels[i]);
            int red = cm.getRed(pixels[i]);
            int green = cm.getGreen(pixels[i]);
            int blue = cm.getBlue(pixels[i]);

            // 增加了图像的亮度
            red = (int) (1.1 * red + 30);
            green = (int) (1.1 * green + 30);
            blue = (int) (1.1 * blue + 30);
            if (red >= 255) {
                red = 255;
            }
            if (green >= 255) {
                green = 255;
            }
            if (blue >= 255) {
                blue = 255;
            }
            pixels[i] = alpha << 24 | red << 16 | green << 8 | blue;
        }
        // 将数组中的象素产生一个图像
        return ImageIOHelper.imageProducerToBufferedImage(new MemoryImageSource(iw, ih,pixels, 0, iw));
    }

    /** 转换为黑白灰度图 */
    public BufferedImage grayFilter() {
        ColorSpace cs = ColorSpace.getInstance(ColorSpace.CS_GRAY);
        ColorConvertOp op = new ColorConvertOp(cs, null);
        return op.filter(image, null);
    }

    /** 平滑缩放 */
    public BufferedImage scaling(double s) {
        AffineTransform tx = new AffineTransform();
        tx.scale(s, s);
        AffineTransformOp op = new AffineTransformOp(tx, AffineTransformOp.TYPE_BILINEAR);
        return op.filter(image, null);
    }

    public BufferedImage scale(Float s) {
        int srcW = image.getWidth();
        int srcH = image.getHeight();
        int newW = Math.round(srcW * s);
        int newH = Math.round(srcH * s);
        // 先做水平方向上的伸缩变换
        BufferedImage tmp=new BufferedImage(newW, newH, image.getType());
        Graphics2D g= tmp.createGraphics();
        for (int x = 0; x < newW; x++) {
            g.setClip(x, 0, 1, srcH);
            // 按比例放缩
            g.drawImage(image, x - x * srcW / newW, 0, null);
        }

        // 再做垂直方向上的伸缩变换
        BufferedImage dst = new BufferedImage(newW, newH, image.getType());
        g = dst.createGraphics();
        for (int y = 0; y < newH; y++) {
            g.setClip(0, y, newW, 1);
            // 按比例放缩
            g.drawImage(tmp, 0, y - y * srcH / newH, null);
        }
        return dst;
    }
}

ImageIOHelper.java

package com.....common.utils.ocr;
/*
 * ImageIOHelper.java
 */
import java.awt.Graphics2D;
import java.awt.Image;
import java.awt.Toolkit;
import java.awt.image.BufferedImage;
import java.awt.image.DataBufferByte;
import java.awt.image.ImageProducer;
import java.awt.image.WritableRaster;
import java.io.File;
import java.io.IOException;
import java.util.Iterator;
import java.util.Locale;
import javax.imageio.IIOImage;
import javax.imageio.ImageIO;
import javax.imageio.ImageReader;
import javax.imageio.ImageWriteParam;
import javax.imageio.ImageWriter;
import javax.imageio.metadata.IIOMetadata;
import javax.imageio.stream.ImageInputStream;
import javax.imageio.stream.ImageOutputStream;
import javax.swing.JOptionPane;

import com.github.jaiimageio.plugins.tiff.TIFFImageWriteParam;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

public class ImageIOHelper {
    protected transient final static Logger logger = LoggerFactory.getLogger(ImageIOHelper.class);
    public ImageIOHelper() {
    }

    public static File createImage(File imageFile, String imageFormat) {
        File tempFile = null;
        try {
            Iterator<ImageReader> readers = ImageIO.getImageReadersByFormatName

                    (imageFormat);
            ImageReader reader = readers.next();
            ImageInputStream iis = ImageIO.createImageInputStream(imageFile);
            reader.setInput(iis);
            // Read the stream metadata
            IIOMetadata streamMetadata = reader.getStreamMetadata();
            // Set up the writeParam
            TIFFImageWriteParam tiffWriteParam = new TIFFImageWriteParam(Locale.US);
            tiffWriteParam.setCompressionMode(ImageWriteParam.MODE_DISABLED);
            // Get tif writer and set output to file
            Iterator<ImageWriter> writers = ImageIO.getImageWritersByFormatName("tiff");
            ImageWriter writer = writers.next();
            BufferedImage bi = reader.read(0);
            IIOImage image = new IIOImage(bi, null, reader.getImageMetadata(0));
            tempFile = tempImageFile(imageFile);
            ImageOutputStream ios = ImageIO.createImageOutputStream(tempFile);
            writer.setOutput(ios);
            writer.write(streamMetadata, image, tiffWriteParam);
            ios.close();

            writer.dispose();
            reader.dispose();
        } catch (Exception exc) {
            logger.error("异常:", exc);
        }
        return tempFile;
    }

    public static File createImage(BufferedImage bi) {
        File tempFile = null;
        try {
            tempFile = File.createTempFile("tempImageFile", ".tif");
            tempFile.deleteOnExit();
            TIFFImageWriteParam tiffWriteParam = new TIFFImageWriteParam(Locale.US);
            tiffWriteParam.setCompressionMode(ImageWriteParam.MODE_DISABLED);

            // Get tif writer and set output to file
            Iterator<ImageWriter> writers = ImageIO.getImageWritersByFormatName("tiff");
            ImageWriter writer = writers.next();

            IIOImage image = new IIOImage(bi, null, null);
            tempFile = tempImageFile(tempFile);
            ImageOutputStream ios = ImageIO.createImageOutputStream(tempFile);
            writer.setOutput(ios);
            writer.write(null, image, tiffWriteParam);
            ios.close();
            writer.dispose();
        } catch (Exception exc) {
            logger.error("异常:", exc);
        }
        return tempFile;
    }


    public static File tempImageFile(File imageFile) {
        String path = imageFile.getPath();
        StringBuffer strB = new StringBuffer(path);
        strB.insert(path.lastIndexOf('.'), 0);

        return new File(strB.toString().replaceFirst("(?<=\\.)(\\w+)$", "tif"));
    }

    public static BufferedImage getImage(File imageFile) {
        BufferedImage al = null;
        try {
            String imageFileName = imageFile.getName();
            String imageFormat = imageFileName.substring(imageFileName.lastIndexOf('.') +

                    1);
            Iterator<ImageReader> readers = ImageIO.getImageReadersByFormatName

                    (imageFormat);
            ImageReader reader = readers.next();

            if (reader == null) {
                JOptionPane.showConfirmDialog(null,
                        "Need to install JAI Image I/O package.");
                return null;
            }

            ImageInputStream iis = ImageIO.createImageInputStream(imageFile);
            reader.setInput(iis);

            al = reader.read(0);

            reader.dispose();
        } catch (IOException ioe) {
            System.err.println(ioe.getMessage());
        } catch (Exception e) {
            System.err.println(e.getMessage());
        }

        return al;
    }

    public static BufferedImage imageToBufferedImage(Image image) {
        BufferedImage bufferedImage = new BufferedImage(image.getWidth(null),

                image.getHeight(null),
                BufferedImage.TYPE_INT_RGB);
        Graphics2D g = bufferedImage.createGraphics();
        g.drawImage(image, 0, 0, null);
        return bufferedImage;
    }

    public static BufferedImage imageProducerToBufferedImage(ImageProducer imageProducer) {
        return imageToBufferedImage(Toolkit.getDefaultToolkit().createImage(imageProducer));
    }

    public static byte[] image_byte_data(BufferedImage image) {
        WritableRaster raster = image.getRaster();
        DataBufferByte buffer = (DataBufferByte) raster.getDataBuffer();
        return buffer.getData();
    }
}

        然后在代码中调用处理即可,

        if(dataFile.exists()){
            File tempImage = ImageIOHelper.createImage(dataFile, "jpg");
			ImageIO.scanForPlugins();
			Tesseract instance = Tesseract.getInstance(); // JNA Interface Mapping
			try {
				String result = instance.doOCR(tempImage).trim();
				System.err.println("解析结果: "+result);
			} catch (TesseractException e) {
				e.printStackTrace();
			}
		} else {
			System.err.println("找不到文件");
		}

            恭喜你,已经完成了Java调用tess4j图像识别的简单功能,至于识别率的高低,取决于图片采集、处理以及字库的完善和训练,希望对大家有所帮助,需要用到的或者有兴趣的童鞋可以自己研究一下~

相关信息
字库训练https://github.com/tesseract-ocr/langdata

 

转载于:https://my.oschina.net/u/589182/blog/737060

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值