Spring Boot 集成 Tess4J 实现图片OCR文字识别
2026/6/26 20:51:19 网站建设 项目流程

目录:

  • 一、环境准备
  • 二、Maven项目依赖引入(pom.xml)
  • 三、配置Tess4J
    • 1.配置文件(application.yml)
    • 2.Tesseract配置类(TesseractConfig.java)
  • 四、核心代码
    • 1.服务层(OcrService.java)
    • 2.接口层OcrController
  • 五、扩展识别精度优化
    • 1. 基础预处理类
    • 2. 完整OCR处理流程

一、环境准备

1.安装Tesseract OCR 引擎

  • Windows: 下载并安装 Tesseract 安装包。安装后,需要将 Tesseract 的安装路径添加到系统环境变量中。
  • Linux: 使用包管理器安装,例如sudo apt-get install tesseract-ocr。
  • macOS: 使用 Homebrew 安装,命令为 brew install tesseract。

2.下载语言数据包(tessdata)

  • Tesseract 需要语言数据包才能识别特定语言。你需要下载chi_sim.traineddata(简体中文)
    和eng.traineddata(英文) 等文件。

重要:路径中不要包含中文或空格。 将这些文件放在一个固定的目录中,
例如:
D:/tessdata (Windows) 或 /usr/local/share/tessdata(Linux/macOS)。

二、Maven项目依赖引入(pom.xml)

在你的pom.xml文件中添加 Tess4J 的依赖。如果你使用的是 Spring Boot 3 (JDK 17+),建议使用 4.5.6 或更高版本以获得更好的兼容性。

<dependencies><!--Tess4J 依赖--><dependency> <groupId>net.sourceforge.tess4j</groupId> <artifactId>tess4j</artifactId> <version>5.3.0</version> <!-- 推荐使用较新版本 --> </dependency></dependencies>

三、配置Tess4J

创建一个配置类,将Tesseract 实例定义为 Spring Bean,方便在项目中注入使用。通过配置文件来管理数据路径和识别语言,使配置更灵活。

1.配置文件(application.yml)

tess4j:data-path:D:/tessdata# 替换为你存放语言数据包的绝对路径language:chi_sim+eng# 设置识别语言,chi_sim为中文,eng为英文

2.Tesseract配置类(TesseractConfig.java)

packagecom.example.ocr.config;importnet.sourceforge.tess4j.Tesseract;importorg.springframework.beans.factory.annotation.Value;importorg.springframework.context.annotation.Bean;importorg.springframework.context.annotation.Configuration;@ConfigurationpublicclassTesseractConfig{@Value("${tess4j.data-path}")privateStringdataPath;@Value("${tess4j.language}")privateStringlanguage;@BeanpublicTesseracttesseract(){Tesseracttesseract=newTesseract();tesseract.setDatapath(dataPath);// 设置tessdata目录路径tesseract.setLanguage(language);// 设置识别语言returntesseract;}}

四、核心代码

接下来创建Service和Controller来提供图片识别功能。

1.服务层(OcrService.java)

该服务负责接收图片文件,并将其转换为BufferedImage后交给Tesseract处理。

packagecom.example.ocr.service;importnet.sourceforge.tess4j.Tesseract;importnet.sourceforge.tess4j.TesseractException;importorg.springframework.stereotype.Service;importorg.springframework.web.multipart.MultipartFile;importjavax.imageio.ImageIO;importjava.awt.image.BufferedImage;importjava.io.ByteArrayInputStream;importjava.io.IOException;@ServicepublicclassOcrService{privatefinalTesseracttesseract;publicOcrService(Tesseracttesseract){this.tesseract=tesseract;}/** * 识别图片中的文字 * @param imageFile 上传的图片文件 * @return 识别出的文本 */publicStringrecognizeText(MultipartFileimageFile)throwsIOException,TesseractException{// 将 MultipartFile 转换为 BufferedImageBufferedImageimage=ImageIO.read(newByteArrayInputStream(imageFile.getBytes()));if(image==null){thrownewIOException("无法读取图片,请检查图片格式是否支持 (如PNG, JPG)");}// 调用 Tesseract 进行识别returntesseract.doOCR(image);}}

2.接口层OcrController

提供一个 REST 接口,用于接收前端上传的图片并返回识别结果。

packagecom.example.ocr.controller;importcom.example.ocr.service.OcrService;importorg.springframework.web.bind.annotation.*;importorg.springframework.web.multipart.MultipartFile;@RestController@RequestMapping("/ocr")publicclassOcrController{privatefinalOcrServiceocrService;publicOcrController(OcrServiceocrService){this.ocrService=ocrService;}@PostMapping("/recognize")publicStringrecognizeImage(@RequestParam("file")MultipartFilefile)throwsException{returnocrService.recognizeText(file);}}

五、扩展识别精度优化

Tesseract 的识别效果与图片质量密切相关。通过预处理图片可以显著提升识别准确率。
图像预处理: 在调用doOCR之前,可以对BufferedImage进行以下处理:

  • 灰度化: 将彩色图片转换为灰度图,减少颜色干扰。

  • 二值化: 将灰度图转换为只有黑白两色的图像,能有效去除背景噪音。

  • 降噪: 使用算法去除图片上的噪点。

  • 调整DPI: 对于文档扫描件,300 DPI 是理想的识别分辨率。

  • 设置PSM (Page Segmentation Mode): 根据图片内容类型调整 PSM 模式。例如,对于单行文本(如验证码),可以设置为 SINGLE_LINE;对于普通文档,使用默认的 AUTO 即可。

1. 基础预处理类

importjava.awt.Color;importjava.awt.image.BufferedImage;importjava.io.File;importjava.io.IOException;importjavax.imageio.ImageIO;publicclassImagePreprocessor{/** * 灰度化处理 */publicstaticBufferedImagegrayScale(BufferedImageimage){intwidth=image.getWidth();intheight=image.getHeight();BufferedImagegrayImage=newBufferedImage(width,height,BufferedImage.TYPE_BYTE_GRAY);for(inty=0;y<height;y++){for(intx=0;x<width;x++){intrgb=image.getRGB(x,y);intr=(rgb>>16)&0xff;intg=(rgb>>8)&0xff;intb=rgb&0xff;// 使用加权平均法,人眼对绿色最敏感intgray=(int)(0.299*r+0.587*g+0.114*b);intnewPixel=(gray<<16)|(gray<<8)|gray;grayImage.setRGB(x,y,newPixel);}}returngrayImage;}/** * 二值化处理(Otsu算法) */publicstaticBufferedImagebinary(BufferedImageimage){BufferedImagegrayImage=grayScale(image);intwidth=grayImage.getWidth();intheight=grayImage.getHeight();BufferedImagebinaryImage=newBufferedImage(width,height,BufferedImage.TYPE_BYTE_BINARY);// 计算灰度直方图int[]histogram=newint[256];for(inty=0;y<height;y++){for(intx=0;x<width;x++){intgray=grayImage.getRGB(x,y)&0xff;histogram[gray]++;}}// Otsu算法计算最佳阈值floatsum=0;for(inti=0;i<256;i++){sum+=i*histogram[i];}floatsumB=0;intwB=0;intwF=0;floatvarMax=0;intthreshold=0;inttotal=width*height;for(intt=0;t<256;t++){wB+=histogram[t];if(wB==0)continue;wF=total-wB;if(wF==0)break;sumB+=t*histogram[t];floatmB=sumB/wB;floatmF=(sum-sumB)/wF;floatvarBetween=(float)wB*(float)wF*(mB-mF)*(mB-mF);if(varBetween>varMax){varMax=varBetween;threshold=t;}}// 应用阈值for(inty=0;y<height;y++){for(intx=0;x<width;x++){intgray=grayImage.getRGB(x,y)&0xff;intnewPixel=(gray>threshold)?Color.WHITE.getRGB():Color.BLACK.getRGB();binaryImage.setRGB(x,y,newPixel);}}returnbinaryImage;}/** * 降噪处理(领域检测法) */publicstaticBufferedImagedenoise(BufferedImageimage){intwidth=image.getWidth();intheight=image.getHeight();BufferedImagedenoisedImage=newBufferedImage(width,height,image.getType());// 边界处理for(intx=0;x<width;x++){for(inty=0;y<height;y++){denoisedImage.setRGB(x,y,image.getRGB(x,y));}}// 降噪核心算法for(inty=1;y<height-1;y++){for(intx=1;x<width-1;x++){if(isBlack(image.getRGB(x,y))){intblackCount=0;// 检查周围8个像素if(isBlack(image.getRGB(x-1,y-1)))blackCount++;if(isBlack(image.getRGB(x,y-1)))blackCount++;if(isBlack(image.getRGB(x+1,y-1)))blackCount++;if(isBlack(image.getRGB(x-1,y)))blackCount++;if(isBlack(image.getRGB(x+1,y)))blackCount++;if(isBlack(image.getRGB(x-1,y+1)))blackCount++;if(isBlack(image.getRGB(x,y+1)))blackCount++;if(isBlack(image.getRGB(x+1,y+1)))blackCount++;// 如果周围黑色像素少于5个,则认为是噪点if(blackCount<5){denoisedImage.setRGB(x,y,Color.WHITE.getRGB());}else{denoisedImage.setRGB(x,y,image.getRGB(x,y));}}else{denoisedImage.setRGB(x,y,image.getRGB(x,y));}}}returndenoisedImage;}/** * 调整DPI(通过缩放实现) */publicstaticBufferedImageadjustDPI(BufferedImageimage,inttargetDPI){intwidth=image.getWidth();intheight=image.getHeight();intcurrentDPI=72;// 默认DPI// 计算缩放比例doublescale=(double)targetDPI/currentDPI;intnewWidth=(int)(width*scale);intnewHeight=(int)(height*scale);BufferedImagescaledImage=newBufferedImage(newWidth,newHeight,image.getType());for(inty=0;y<newHeight;y++){for(intx=0;x<newWidth;x++){intsrcX=(int)(x/scale);intsrcY=(int)(y/scale);if(srcX<width&&srcY<height){scaledImage.setRGB(x,y,image.getRGB(srcX,srcY));}}}returnscaledImage;}/** * 设置PSM模式 */publicstaticvoidsetPSM(ITesseracttesseract,Stringmode){tesseract.setTessVariable("tessedit_pageseg_mode",mode);}// 辅助方法privatestaticbooleanisBlack(intcolor){Colorc=newColor(color);return(c.getRed()+c.getGreen()+c.getBlue())<=300;}privatestaticbooleanisWhite(intcolor){Colorc=newColor(color);return(c.getRed()+c.getGreen()+c.getBlue())>300;}}

2. 完整OCR处理流程

importnet.sourceforge.tess4j.*;importjavax.imageio.ImageIO;importjava.awt.image.BufferedImage;importjava.io.File;publicclassOCRProcessor{publicstaticStringrecognizeText(FileimageFile){try{// 读取图像BufferedImageimage=ImageIO.read(imageFile);// 1. 灰度化BufferedImagegrayImage=ImagePreprocessor.grayScale(image);// 2. 二值化BufferedImagebinaryImage=ImagePreprocessor.binary(grayImage);// 3. 降噪BufferedImagedenoisedImage=ImagePreprocessor.denoise(binaryImage);// 4. 调整DPI到300BufferedImagehighDPIImage=ImagePreprocessor.adjustDPI(denoisedImage,300);// 5. 初始化TesseractITesseracttesseract=newTesseract();tesseract.setDatapath("C:/Program Files/Tesseract-OCR/tessdata");tesseract.setLanguage("eng");// 或 "chi_sim" 用于中文// 6. 设置PSM模式// PSM 6: 假设单行文本// PSM 7: 假设文本在单个 uniform 块中// PSM 3: 完全自动页面分割,但适合具有明显文本区域的页面ImagePreprocessor.setPSM(tesseract,"6");// 7. 执行OCRStringresult=tesseract.doOCR(highDPIImage);returnresult.trim();}catch(Exceptione){e.printStackTrace();return"识别失败: "+e.getMessage();}}publicstaticvoidmain(String[]args){StringimagePath="your_image.jpg";Stringresult=recognizeText(newFile(imagePath));System.out.println("识别结果: "+result);}}

需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询