python 安装 wand pillow image 纯图片PDF转图片后调用百度OCR

一、安装库

  • Linux 安装
    pip install wand
    yum update
    yum -y install ImageMagick-devel
    装下最新版本ghostscript,可以参考我的文章《Linux 编译安装 ghostscript 最新版》
    上面步骤,我自己是在docker里面安装测试的,没问题
  • Mac安装
    pip install wand
    brew install ghostscript (如装过且版本低,brew upgrade ghostscript 更新下,发现有的PDF会报错,更新就好了
    ----2018-10-22 11:52:37补充,这里一定要升级到最新版,否则很容易报错,
    两个版本的gs有8.15和9.04,前者静态编译出来4M大小,后者是16M大小。前者是打印文字需要装字库,但是后者不需要。前者对PDF的处理不是太完善,其实也可以理解,8.15版本是2004年发布的,而9.04是2011年发布的。

    brew install imagemagick (默认是装7的,这个版本用起来会报错)
    brew install imagemagick@6
    ln -s /usr/local/Cellar/imagemagick@6/6.9.10-12/lib/libMagickWand-6.Q16.dylib /usr/local/lib/libMagickWand.dylib
    (这最后一步很重要,要不然会报错,我这里卡了一会)

二、开整
大体思路:

  1. 使用wand处理纯图片的PDF文件(转成图片,当然文字版PDF也能使用)
  2. 使用Image库处理PDF生成的图片
  3. 图片传给百度OCR识别

贴代码吧

# coding=utf-8
from __future__ import division

import StringIO
import math
from wand.image import Image
# 这里我起了个别名
from PIL import Image as PImage

# 百度OCR最大长度
bai_du_ocr_max = 4096

#主要方法
def convert(file_name, target_width=1500):
   try:
       with Image(filename=file_name) as img:
           image_page_num = len(img.sequence)

           # PDF里面只有一张图片
           if image_page_num == 1:
               # 获取最终图片宽高
               target_width, target_height = _get_one_info(target_width, img.width, img.height)

               # 缩放,文档上说比resize速度快
               img.sample(target_width, target_height)

               # 如果最终高度大于百度最大高度,则crop
               if target_height > bai_du_ocr_max:
                   img.crop(0, 0, target_width, bai_du_ocr_max)

               # img.save(filename='%s.jpg' % (str(int(time.time())) + '_' + str(img.width)))
               result = img.make_blob('jpg')

               # 下面是准备二值化,发现总体速度还不如直接传给百度
               # paste_image = PImage.open(StringIO.StringIO(img.make_blob('jpg')))
               # paste_image = paste_image.convert("L")
               # paste_image.show()
               # d = StringIO.StringIO()
               # paste_image.save(d, 'JPEG')
               # result = d.getvalue()

           # PDF里面有一张以上图片
           else:
               # 多张时,获取最终宽高、拼接页数
               target_width, target_height, page_num = _get_more_info(
                   target_width, img.width, img.height, image_page_num
               )

               # 生成粘贴的背景图 (测试多次,发现L比RGB快)
               paste_image = PImage.new('L', (target_width, target_height))

               # 拼接图片
               for i in range(0, page_num):
                   image = Image(image=img.sequence[i])
                   # 计算一张图的高度
                   one_img_height = int(target_height / page_num)
                   # 缩放
                   image.sample(target_width, one_img_height)
                   # 将wand库文件转成PIL库文件
                   pasted_image = PImage.open(StringIO.StringIO(image.make_blob('jpg')))
                   # 将图片粘贴到背景图
                   paste_image.paste(pasted_image, (0, one_img_height * i))

               # 如果最终高度大于百度最大高度,则crop
               if target_height > bai_du_ocr_max:
                   paste_image = paste_image.crop((0, 0, target_width, bai_du_ocr_max))

               # 从内存中读取文件
               d = StringIO.StringIO()
               # 这里是JPEG不是JPG
               paste_image.save(d, 'JPEG')
               result = d.getvalue()
               # paste_image.save('%s.jpg' % (str(int(time.time())) + '_' + str(img.width)))
               # 测试的时候可以打开
               # paste_image.show()
   except Exception as e:
       result = False
   return result


# 一张时获取宽高,如果图片宽度大于我们想要的宽度,则等比缩放图片高度
def _get_one_info(target_width, img_width, img_height):
   if img_width > target_width:
       ratio = target_width / img_width
       target_height = int(ratio * img_height)
   else:
       target_width = img_width
       target_height = img_height
   return target_width, target_height


# 多张时获取宽高和拼接页数
def _get_more_info(target_width, img_width, img_height, image_page_num):
   one_width, one_height = _get_one_info(target_width, img_width, img_height)
   if one_height < bai_du_ocr_max:
       # 百度最大高度除以每张图高度,向上取整,即拼接图片的数量
       num = int(math.ceil(bai_du_ocr_max / one_height))
       # 取拼接数和总页数的最小值
       page_num = min(num, image_page_num)
       return one_width, one_height * page_num, page_num
   else:
       return one_width, one_height, 1  # 1页


# 调试时候用
def _ocr(content):
   url = '百度OCR链接(自己去百度OCR官网申请就行)'
   img = base64.b64encode(content)
   params = {"image": img}
   params = urllib.urlencode(params)

   request = urllib2.Request(url, params)
   request.add_header('Content-Type', 'application/x-www-form-urlencoded')
   response = urllib2.urlopen(request)
   content = response.read()
   # print content
   dict_content = json.loads(content)
   text = "\n".join(map(lambda x: x["words"], dict_content["words_result"]))
   return text


# 调试时候用
def _write_file(path, data, type="w"):
   try:
       f = open(path, '%sb' % type)
   except:
       f = open(path.encode("utf-8"), '%sb' % type)
   f.write(data)
   f.close()


# 调试时候用
if __name__ == '__main__':
   import sys
   import base64
   import json
   import urllib
   import urllib2
   import time

   start = time.time()
   source_file = sys.argv[1]
   ret = convert(source_file, 1500)
   end = time.time()
   # 这里我统一保存下文件,方便打开观察
   _write_file(str(end) + '.jpg', ret)
   if ret:
       text = _ocr(ret)
   end_parse = time.time()
   print '____________________________________________'
   print end - start
   print end_parse - end
   print '+++++++++++++++++++++++++++++++++++++++++++++'
   print text

调用方法(python文件名字和文件路径自己替换)

python pdf2img.py file_path   

PS:
我这里一张和多张时分开的,我发现我的PDF文件大多数都是纯图片且都是一页的(非图片PDF可以用tika解出来里面的文字),极少数是多页。另外,1页的时候只用wand一个库就行,不需要粘贴到大图上,会省去一些时间。有些问题没做就是,并发高的时候,服务器内存可能扛不住,毕竟图片都是在内存里面。

  • 1
    点赞
  • 10
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值