SpringBoot集成Tess4J实现图片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)
package com.example.ocr.config;
import net.sourceforge.tess4j.Tesseract;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
@Configuration
publicclass TesseractConfig {
@Value("${tess4j.data-path}")
private String dataPath;
@Value("${tess4j.language}")
private String language;
@Bean
public Tesseract tesseract() {
Tesseract tesseract = new Tesseract();
tesseract.setDatapath(dataPath); // 设置tessdata目录路径
tesseract.setLanguage(language); // 设置识别语言
return tesseract;
}
}
四、核心代码
接下来创建Service和Controller来提供图片识别功能。
1.服务层(OcrService.java)
该服务负责接收图片文件,并将其转换为BufferedImage后交给Tesseract处理。
package com.example.ocr.service;
import net.sourceforge.tess4j.Tesseract;
import net.sourceforge.tess4j.TesseractException;
import org.springframework.stereotype.Service;
import org.springframework.web.multipart.MultipartFile;
import javax.imageio.ImageIO;
import java.awt.image.BufferedImage;
import java.io.ByteArrayInputStream;
import java.io.IOException;
@Service
publicclass OcrService {
privatefinal Tesseract tesseract;
public OcrService(Tesseract tesseract) {
this.tesseract = tesseract;
}
/**
* 识别图片中的文字
* @param imageFile 上传的图片文件
* @return 识别出的文本
*/
public String recognizeText(MultipartFile imageFile) throws IOException, TesseractException {
// 将 MultipartFile 转换为 BufferedImage
BufferedImage image = ImageIO.read(new ByteArrayInputStream(imageFile.getBytes()));
if (image == null) {
thrownew IOException("无法读取图片,请检查图片格式是否支持 (如PNG, JPG)");
}
// 调用 Tesseract 进行识别
return tesseract.doOCR(image);
}
}
2.接口层OcrController
提供一个 REST 接口,用于接收前端上传的图片并返回识别结果。
package com.example.ocr.controller;
import com.example.ocr.service.OcrService;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.multipart.MultipartFile;
@RestController
@RequestMapping("/ocr")
publicclass OcrController {
privatefinal OcrService ocrService;
public OcrController(OcrService ocrService) {
this.ocrService = ocrService;
}
@PostMapping("/recognize")
public String recognizeImage(@RequestParam("file") MultipartFile file) throws Exception {
return ocrService.recognizeText(file);
}
}
五、扩展识别精度优化
Tesseract 的识别效果与图片质量密切相关。通过预处理图片可以显著提升识别准确率。
图像预处理: 在调用doOCR之前,可以对BufferedImage进行以下处理:
- 灰度化: 将彩色的图片转换为灰度图,减少颜色干扰。
- 二值化: 将灰度图转换为只有黑白两色的图像,能有效去除背景噪音。
- 降噪: 使用算法去除图片上的噪点。
- 调整DPI: 对于文档扫描件,300 DPI 是理想的识别分辨率。
- 设置PSM (Page Segmentation Mode): 根据图片内容类型调整 PSM 模式。例如,对于单行文本(如验证码),可以设置为 SINGLE_LINE;对于普通文档,使用默认的 AUTO 即可。
1. 基础预处理类
import java.awt.Color;
import java.awt.image.BufferedImage;
import java.io.File;
import java.io.IOException;
import javax.imageio.ImageIO;
public class ImagePreprocessor {
/**
* 灰度化处理
*/
public static BufferedImage grayScale(BufferedImage image) {
int width = image.getWidth();
int height = image.getHeight();
BufferedImage grayImage = new BufferedImage(width, height, BufferedImage.TYPE_BYTE_GRAY);
for (int y = 0; y < height; y++) {
for (int x = 0; x < width; x++) {
int rgb = image.getRGB(x, y);
int r = (rgb >> 16) & 0xff;
int g = (rgb >> 8) & 0xff;
int b = rgb & 0xff;
// 使用加权平均法,人眼对绿色最敏感
int gray = (int) (0.299 * r + 0.587 * g + 0.114 * b);
int newPixel = (gray << 16) | (gray << 8) | gray;
grayImage.setRGB(x, y, newPixel);
}
}
return grayImage;
}
/**
* 二值化处理(Otsu算法)
*/
public static BufferedImage binary(BufferedImage image) {
BufferedImage grayImage = grayScale(image);
int width = grayImage.getWidth();
int height = grayImage.getHeight();
BufferedImage binaryImage = new BufferedImage(width, height, BufferedImage.TYPE_BYTE_BINARY);
// 计算灰度直方图
int[] histogram = new int[256];
for (int y = 0; y < height; y++) {
for (int x = 0; x < width; x++) {
int gray = grayImage.getRGB(x, y) & 0xff;
histogram[gray]++;
}
}
// Otsu算法计算最佳阈值
float sum = 0;
for (int i = 0; i < 256; i++) {
sum += i * histogram[i];
}
float sumB = 0;
int wB = 0;
int wF = 0;
float varMax = 0;
int threshold = 0;
int total = width * height;
for (int t = 0; t < 256; t++) {
wB += histogram[t];
if (wB == 0) continue;
wF = total - wB;
if (wF == 0) break;
sumB += t * histogram[t];
float mB = sumB / wB;
float mF = (sum - sumB) / wF;
float varBetween = (float) wB * (float) wF * (mB - mF) * (mB - mF);
if (varBetween > varMax) {
varMax = varBetween;
threshold = t;
}
}
// 应用阈值
for (int y = 0; y < height; y++) {
for (int x = 0; x < width; x++) {
int gray = grayImage.getRGB(x, y) & 0xff;
int newPixel = (gray > threshold) ? Color.WHITE.getRGB() : Color.BLACK.getRGB();
binaryImage.setRGB(x, y, newPixel);
}
}
return binaryImage;
}
/**
* 降噪处理(领域检测法)
*/
public static BufferedImage denoise(BufferedImage image) {
int width = image.getWidth();
int height = image.getHeight();
BufferedImage denoisedImage = new BufferedImage(width, height, image.getType());
// 边界处理
for (int x = 0; x < width; x++) {
for (int y = 0; y < height; y++) {
denoisedImage.setRGB(x, y, image.getRGB(x, y));
}
}
// 降噪核心算法
for (int y = 1; y < height - 1; y++) {
for (int x = 1; x < width - 1; x++) {
if (isBlack(image.getRGB(x, y))) {
int blackCount = 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));
}
}
}
return denoisedImage;
}
/**
* 调整DPI(通过缩放实现)
*/
public static BufferedImage adjustDPI(BufferedImage image, int targetDPI) {
int width = image.getWidth();
int height = image.getHeight();
int currentDPI = 72; // 默认DPI
// 计算缩放比例
double scale = (double) targetDPI / currentDPI;
int newWidth = (int) (width * scale);
int newHeight = (int) (height * scale);
BufferedImage scaledImage = new BufferedImage(newWidth, newHeight, image.getType());
for (int y = 0; y < newHeight; y++) {
for (int x = 0; x < newWidth; x++) {
int srcX = (int) (x / scale);
int srcY = (int) (y / scale);
if (srcX < width && srcY < height) {
scaledImage.setRGB(x, y, image.getRGB(srcX, srcY));
}
}
}
return scaledImage;
}
/**
* 设置PSM模式
*/
public static void setPSM(ITesseract tesseract, String mode) {
tesseract.setTessVariable("tessedit_pageseg_mode", mode);
}
// 辅助方法
private static boolean isBlack(int color) {
Color c = new Color(color);
return (c.getRed() + c.getGreen() + c.getBlue()) <= 300;
}
private static boolean isWhite(int color) {
Color c = new Color(color);
return (c.getRed() + c.getGreen() + c.getBlue()) > 300;
}
}
2. 完整OCR处理流程
import net.sourceforge.tess4j.*;
import javax.imageio.ImageIO;
import java.awt.image.BufferedImage;
import java.io.File;
public class OCRProcessor {
public static String recognizeText(File imageFile) {
try {
// 读取图像
BufferedImage image = ImageIO.read(imageFile);
// 1. 灰度化
BufferedImage grayImage = ImagePreprocessor.grayScale(image);
// 2. 二值化
BufferedImage binaryImage = ImagePreprocessor.binary(grayImage);
// 3. 降噪
BufferedImage denoisedImage = ImagePreprocessor.denoise(binaryImage);
// 4. 调整DPI到300
BufferedImage highDPIImage = ImagePreprocessor.adjustDPI(denoisedImage, 300);
// 5. 初始化Tesseract
ITesseract tesseract = new Tesseract();
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. 执行OCR
String result = tesseract.doOCR(highDPIImage);
return result.trim();
} catch (Exception e) {
e.printStackTrace();
return "识别失败: " + e.getMessage();
}
}
public static void main(String[] args) {
String imagePath = "your_image.jpg";
String result = recognizeText(new File(imagePath));
System.out.println("识别结果: " + result);
}
}
到此这篇关于SpringBoot集成Tess4J实现图片OCR文字识别的文章就介绍到这了,更多相关SpringBoot图片OCR文字识别内容请搜索脚本之家以前的文章或继续浏览下面的相关文章希望大家以后多多支持脚本之家!
相关文章
SpringBootWeb 入门了解 Swagger 的具体使用
这篇文章主要介绍了SpringBootWeb 入门了解 Swagger 的具体使用,Swagger 框架可以根据已经实现的方法或者类,通过页面的方式直观清晰的查看或者进行测试该方法,需要的朋友可以参考下2024-08-08


最新评论