不可复制的PDF转成双层可复制PDF
有些PDF是通过扫描或者虚拟打印机生成的,这些PDF不可复制里边的内容
市面上的工具一般都是收费或者有水印,所以就萌生了自己搞一个的想法:
使用了以下三个开源库
- PdfiumViewer PDF预览及可编辑PDF的提取
- PDFsharp 生成PDF
- PaddleSharp 对图片OCR识别
大概思路是:
用PdfiumViewer 渲染显示,并转PDF为图片;
使用PaddleSharp 对提取图片的内容及bbox坐标;
把坐标根据缩放比转成相对于PDF的坐标,并使用PDFsharp 重新生成PDF,如需要保持原有格式需要把1转成的图片重新回写到生成的pdf,文字层为ocg层;
实现双层pdf的效果;
读取PDF到到内存流:
private PdfDocument OpenDocument(string fileName)
{
try
{
return PdfDocument.Load(this, new MemoryStream(File.ReadAllBytes(fileName)));
}
catch (Exception ex)
{
MessageBox.Show(this, ex.Message, Text, MessageBoxButtons.OK, MessageBoxIcon.Error);
return null;
}
}
PDF转图片:
//图片dpi要相对大些,这样ocr识别的更清晰
int dpiX = 96 * 5;
int dpiY = 96 * 5;
var pdfWidth = (int)document.PageSizes[page].Width * 4 / 3;
var pdfHeight = (int)document.PageSizes[page].Height * 4 / 3;
var rotate = PdfRotation.Rotate0;
var flags = PdfRenderFlags.Annotations | PdfRenderFlags.CorrectFromDpi;
using (var image = document.Render(page, pdfWidth, pdfHeight, dpiX, dpiY, rotate, flags)){}
OCR识别:
byte[] sampleImageData = ImageToByte(image);
FullOcrModel model = LocalFullModels.ChineseV3;
using (PaddleOcrAll all = new PaddleOcrAll(model, PaddleDevice.Mkldnn())
{
AllowRotateDetection = true, /* 允许识别有角度的文字 */
Enable180Classification = false, /* 允许识别旋转角度大于90度的文字 */
})
{
// Load local file by following code:
using (Mat src = Cv2.ImDecode(sampleImageData, ImreadModes.Color))
{
PaddleOcrResult result = all.Run(src);
return result;
}
}
图片转成流:
private byte[] ImageToByte(System.Drawing.Image image)
{
MemoryStream ms = new MemoryStream();
if (image == null)
return new byte[ms.Length];
image.Save(ms, System.Drawing.Imaging.ImageFormat.Png);
byte[] BPicture = new byte[ms.Length];
BPicture = ms.GetBuffer();
return BPicture;
}
转换bbox坐标到PDF坐标:bbox坐标是相对于图片的坐标,可以
private System.Drawing.RectangleF ConvertToPDFSize(System.Drawing.RectangleF rectangle, float dpiX, float dpiY, PdfRotation rotate, PdfRenderFlags flags)
{
var width = rectangle.Width;
var height = rectangle.Height;
var x = rectangle.X;
var y = rectangle.Y;
if ((flags & PdfRenderFlags.CorrectFromDpi) != 0)
{
width = (width / dpiX * 72);
height = (height / dpiY * 72);
x = (x / dpiX * 72);
y = (y / dpiY * 72);
}
return new RectangleF(x, y, width, height);
}
bbox坐标框选示例:

由于OCR的限制:转双层pdf只能在x64系统运行,不适用OCR可运行x86和x64,
工具功能:
- 可提取和框选提取可复制和不可复制pdf;
- 可转换不可复制的pdf为双层可复制pdf;
- 可转换不可复制的pdf为可复制pdf;
- 加载图片并提取标注提取内容;
直接下载地址:
https://cloud.189.cn/web/share?code=MZvMb2ZNRbMn(访问码:y9st)
也可按照下放代码自己编译使用,遵循MIT协议
欢迎Start、PR
源码地址:https://github.com/1000374/HM.PdfOcr
不可复制的PDF转成双层可复制PDF的更多相关文章
- PDF转换成DXF文件?PDF转DXF的操作方法
在CAD工作中,经常就需要将绘制完成的图纸文件的格式进行转换,那怎么将PDF文件转换成DXF格式的呢?具体要怎么来进行操作呢?本编教程小编就来教教大家具体操作方法,具体操作如下: 一.工具转换 推荐指 ...
- C# 复制PDF页面到另一个PDF文档
C# 复制PDF页面到另一个PDF文档 有时候我们可能有这样一个需求,那就是把PDF页面从一个PDF文档复制到另一个PDF文档中.由于PDF文档并不像word文档那样好编辑,因此复制也相对没有那么容易 ...
- ABBYY把pdf转换成word的方法
有时候我们在网上下载的资料文献是PDF格式文档,遇到喜欢的字句总忍不住想要收藏起来,但是PDF文档不同于普通的Word文档可以直接进行复制粘贴,需要下载安装相关的编辑工具,才能对文字内容进行编辑.倒不 ...
- 复制pdf文字出来是乱码
PDF文件复制文本为乱码 - longzhinuhou的博客 - CSDN博客 https://blog.csdn.net/longzhinuhou/article/details/83758966 ...
- 如何使用Adobe Reader复制PDF文档上的文字
PDF文档大家常用,但是有没有简单的方法能够提取PDF文档上的文字,然后使用呢?除了将PDF转换成Word,这里介绍一种更为简单实用的方法复制PDF文本文字,Adobe Reader是大家都常用的PD ...
- pdf转换成文本解决格式不统一问题
pdf转换成文本解决格式不统一问题 懒得调OCR服务了,所以快速解决的方法是: pdf转png:https://pdf2png.com/zh/ png转统一格式pdf:adobe acrobat自带增 ...
- C#pdf 切割成图片
引用 using Ghostscript.NET;using Ghostscript.NET.Rasterizer; 需要安装 exe文件 public static GhostscriptVersi ...
- pdf 切割成圖片的方法
/// <summary> /// 将PDF文档转换为图片的方法 /// </summary> /// <param na ...
- Python 将pdf转换成txt(不处理图片)
上一篇文章中已经介绍了简单的python爬网页下载文档,但下载后的文档多为doc或pdf,对于数据处理仍然有很多限制,所以将doc/pdf转换成txt显得尤为重要.查找了很多资料,在linux下要将d ...
- 如何用ABBYY把PDF转换成PPT
在电子科技迅速发展的今天,文件格式转换并不是什么稀罕事,因为现在都是电子化办公,出现很多文件格式,但是不同的场合需要的格式不同,所以常常需要进行文件格式的转换.PDF转换成PPT也是众多文件格式转换中 ...
随机推荐
- hexo博客主题,git上传,报错Template render error的解决方案
报错信息 INFO Start processing FATAL Something's wrong. Maybe you can find the solution here: http://hex ...
- Linux下Oracle单实例配置多监听
Oracle单实例配置多监听 一.前言 有时候我们项目中需要使用Oracle数据库,同时要需要不同的数据源,而Oracle不像Mysql那样直接建个库即可,Oracle是以账号为单位,可以理解为一个账 ...
- Python中的弱引用与基础类型支持情况探究
背景 最近有一个业务场景需要用Python自行实现一个简单的LRU cache,不可避免的接触到了弱引用这一概念,这里记录一下. 强引用 Python内存回收由垃圾回收器自动管理,当一个对象的引用计数 ...
- [爬虫]3.4.1 Scrapy框架的基本使用
Scrapy是一款强大的Python网络爬虫框架,它可以帮助你快速.简洁地编写爬虫程序,处理数据抓取.处理和存储等复杂问题. 1. 安装Scrapy 在开始使用Scrapy之前,你需要先将其安装在你的 ...
- shell 默认参数
#!/bin/bash dst_dir=${2:-/tmp} # 当 $2 为空或null时,设置默认值. docker cp prometheus:$1 $dst_dir
- PXE服务器搭建--ARM
PXE服务搭建 一. 什么是PXE PXE是由Intel公司开发的最新技术,工作于Client/Server的网络模式,支持工作站通过网络从远端服务器下载映像,并由此支持通过网络启动操作系统,在启动过 ...
- JS自制极简日历Demo
这个日历界面不属于任何插件,纯粹用最基本的JS函数获取到每个位置对应的日期,然后再通过遍历拼接table表单的方式赋值到HTML里面进行展示,日历效果的显示,其中使用到的文件只需要一个Jquery的J ...
- 9、Spring之代理模式
9.1.环境搭建 9.1.1.创建module 9.1.2.选择maven 9.1.3.设置module名称和路径 9.1.4.module初始状态 9.1.5.配置打包方式和依赖 <?xml ...
- LeetCode952三部曲之三:再次优化(122ms -> 96ms,超51% -> 超91%)
欢迎访问我的GitHub 这里分类和汇总了欣宸的全部原创(含配套源码):https://github.com/zq2599/blog_demos 本篇概览 本文是<LeetCode952三部曲之 ...
- HTML一键打包APK工具 如何进行实名认证购买和激活
HTML一键打包APK工具 价格表 授权时长 价格 1小时 49 1天 99 1个月 199 1个季度 399 半年 599 1年 799 付费版功能 功能点 免费版 付费版 去除广告信息 × √ 去 ...