起因

上课时候或者下课后想拿课件来做笔记的时候,遇到过一些尴尬。

如果说直接看老师发的 pdf,就会发现滚好多页才会看完一个有效一页。这种 pdf 我个人叫做散装 pdf(P.S.这种情况在用 beamer 做课件的老师更为常见)。

图片

当然,好在老师提供了ppt,我们可以从 ppt 打印为 pdf。

问题的确算是解决了, 直到...

图片

大概由于电脑的某些设置不同,导致了一些内容尴尬地跑出了页面范围... 

有时也会有某些文本因为文本框过窄而自动换行的情况(可能因为我的电脑屏幕比老师的小)等等

种种问题,导致了 ppt 导出的 pdf 没有老师的原始 pdf 美观,甚至还会缺失一些信息内容。

大概有人会说直接看 ppt 不就好了,折腾 pdf 干嘛呢。只能说如果和老师编辑 ppt 使用的操作系统不一致的话,某些字体显示会有一些奇怪的不一致。更重要的一点是,ppt格式不方便挪到 iPad上面做笔记,比如 Marginnote、Noteability、OneNote等等

动手

毕竟众口难调嘛,也不好再麻烦老师来迁就我这种口味刁钻的学生,于是就有了一个看起来有点无聊的想法: 给老师发的散装pdf打包一下。

然后稍微聊下主要思路:

  1. 将每一页 pdf 转为图片,转灰度值后每一页pdf对我们而言就只是一个又一个的二维数组而已了,其中二维数组里面的每一个元素对应着一个像素点的灰度值
  2. 然后对比一下前后两页的数组,两个数组做差后为0的元素即两页相同的部分,不为0的部分对应的就是两页不同的像素点。
    对不同像素点做一定的判断,就可以分析这两页是不是都是同一页有效页,目前代码有两种判断思路:
    1. 变化像素点数目占总像素数目的比例是否超出阈值(阈值是超参数)
    2. 发生变化像素点对应的位置(index),在前一页中的 value 是否与背景色想对应。如果觉得这样判断太严格可以加一个容差范围。
    3. 走过一次for循环之后,我们就得到了每一个有效页第一页的页码,对原pdf文件提取出对应页码,重新保存到新的 pdf 中,就成功地提取出文档的全部"精华"了。

完整代码见 Github

尾声

以后我只用跑一下程序就好了,再也不用打开 ppt,等待我缓慢的电脑加载完office,然后在去找打印的button,或者ctrl+P打印,再选一下保存路径等等一系列麻烦无聊恼人的操作了。🥴

回过头来说一下,代码还没有十分完善,目前第二种方法只能处理纯色的背景,对于特殊背景的 pdf,还要多加几行代码,也不是很麻烦,有兴趣的可以帮我加上呗(懒)。

代码使用简易说明

pdf-helperzdfilter2.py中的

# ========== Config ==================
path = "path/to/lec/pdf"
ignore_files = [
    "pdf_that_u_don't_want_to_filtrate1.pdf",
    "pdf_that_u_don't_want_to_filtrate2.pdf"
]
# ====================================

配置一下:path变量修改为你需要处理的那个文件夹路径,ignore_files为当前文件夹下一些你不想处理的文件名,然后在filter2.py所在文件夹下打开命令行运行程序即可。

python3 filter2.py

代码已经上传GitHub仓库

https://github.com/Benature/pdf-helper/tree/master/pdf_filter