项目中有个ocr软件识别发票信息的需求,实际使用中发现识别率有点低。后来发现对于电子发票,可以直接识别二维码读取部分票面信息,然后用这部分信息作为参数,通过调用税务的接口获取全票面信息。只要是正常的电子发票,识别率差不多是100%。
创作不易,转载请注明出处
<dependency>
<groupId>org.apache.pdfbox</groupId>
<artifactId>pdfbox</artifactId>
<version>2.0.20</version>
</dependency>
<dependency>
<groupId>com.google.zxing</groupId>
<artifactId>core</artifactId>
<version>3.1.0</version>
</dependency>
<dependency>
<groupId>com.google.zxing</groupId>
<artifactId>javase</artifactId>
<version>3.1.0</version>
</dependency>
/**
* 获取电子发票pdf文件中的发票信息
* @param filePath 电子发票路径
* @return 发票信息
*/
public Invoice getInvoiceInfo(String filePath) {
try {
List<BufferedImage> imageList = extractImage(new File(filePath));
if (imageList.isEmpty()) {
logger.info("pdf中未解析出图片,返回空");
return null;
}
MultiFormatReader formatReader = new MultiFormatReader();
//正常解析出来有3张图片,第一张是二维码,其他两张图片是发票上盖的章
BinaryBitmap binaryBitmap = new BinaryBitmap(new HybridBinarizer(new BufferedImageLuminanceSource(imageList.get(0))));
Map hints = new HashMap<>();
hints.put(EncodeHintType.CHARACTER_SET, "utf-8");
Result result = formatReader.decode(binaryBitmap);
if (result == null || StringUtils.isEmpty(result.getText())) {
logger.info("pdf中的第一张图片没有解析了字符串信息,直接返回空");
return null;
}
logger.info("从电子发票中识别出的信息为:{}", result.getText());
// 读取到的信息为 : 01,发票类型,发票代码,发票号码,发票金额,开票日期,校验码,随机产生的摘要信息
String[] infos = result.getText().split(",");
if (infos.length != 8) {
logger.info("pdf中的第一张图片解析出的字符串数组长度不为8,返回空。");
return null;
}
Invoice invoice = new Invoice();
invoice.setInvoiceType(infos[1]); //发票类型
invoice.setInvoiceCode(infos[2]); //发票代码
invoice.setInvoiceNo(infos[3]); // 发票号码
invoice.setAmount(new BigDecimal(infos[4])); // 发票金额
invoice.setInvoiceDate(DateUtils.parseDate(infos[5], "yyyyMMdd")); //开票日期
invoice.setCheckCode(infos[6]); // 校验码
return invoice;
} catch (Exception e) {
logger.info("解析pdf中的二维码出现异常", e);
return null;
}
}
/**
* 提取电子发票里面的图片
* @param pdfFile 电子发票文件对象
* @return pdf中解析出的图片列表
* @throws Exception
*/
private List<BufferedImage> extractImage(File pdfFile) throws Exception {
List<BufferedImage> imageList = new ArrayList<BufferedImage>();
PDDocument document = PDDocument.load(pdfFile);
PDPage page = document.getPage(0); //电子发票只有一页
PDResources resources = page.getResources();
for (COSName name : resources.getXObjectNames()) {
if (resources.isImageXObject(name)) {
PDImageXObject obj = (PDImageXObject)resources.getXObject(name);
imageList.add(obj.getImage());
}
}
return imageList;
}
创作不易,转载请注明出处