乐趣区

关于人工智能:医案图片pdf转文字的方法

工作:提取医案,有局部医案存在于 pdf 书中,但这些 pdf 是图片格式的,须要把这些内容转换成为文字内容。

思路 :把 pdf 文件转换为单张图片汇合,而后再对单张图片进行 ocr 辨认,对辨认的后果文字进行拼接。
利用 pypdf2 模块,读取 pdf,读取二进制内容,利用 wand 模块将其中某一页转换为图片并保留。

1 读取 pdf 并转换为图片

装置 pypdf2 包。
pip install pypdf2
装置 python 包:wand
pip install wand
wand 的文档:https://docs.wand-py.org/

上代码:

import io
from wand.image import Image
from wand.color import Color
from PyPDF2 import PdfFileReader, PdfFileWriter
import json


memo = {}
# 用 PyPDF2 的 PdfFileReader 读取 pdf 文件
def getPdfReader(filename):
    reader = memo.get(filename, None)
    if reader is None:
        reader = PdfFileReader(filename, strict=False)
        memo[filename] = reader
    return reader

# 将制订页码的 pdf 页面转换为图片格式
def _run_convert(filename, page, res=120):
    idx = page + 1
    pdfile = getPdfReader(filename)
    pageObj = pdfile.getPage(page) # page 是从 0 开始的
    dst_pdf = PdfFileWriter()
    dst_pdf.addPage(pageObj)
    pdf_bytes = io.BytesIO()
    dst_pdf.write(pdf_bytes)
    pdf_bytes.seek(0)
    img = Image(file=pdf_bytes, resolution=res)
    img.format = 'png'
    img.compression_quality = 100
    img.background_color = Color("white")
    img_path = '{}{}.png'.format(filename[:filename.rindex('.')], idx)
    img.save(filename=img_path)
    img.destroy()

执行之后会报错,短少 ImageMagick。
装置 ImageMagick
ImageMagick 是一款收费开源的图片编辑软件。既能够通过命令行应用,也能够通过 C /C++、Perl、Java、PHP、Python 或 Ruby 调用库编程来实现。ImageMagic 的次要精力集中在性能,缩小 bug 以及提供稳固的 API 和 ABI 上。
下载地址:https://imagemagick.org/scrip…
应用办法能够参考:https://www.cnblogs.com/Renyi…

之后,持续报错,短少另外一个 软件 Ghostscript

wand.exceptions.DelegateError: FailedToExecuteCommand `"gswin64c.exe" -q -dQUIET -dSAFER -dBATCH -dNOPAUSE -dNOPROMPT -dMaxBitmap=500000000 -dAlignToPixels=0 -dGridFitTT=2 "-sDEVICE=pngalpha" -dTextAlphaBits=4 -dGraphicsAlphaBits=4 "-r120x120" -dPrinted=false  "-sOutputFile=C:/Users/ADMINI~1/AppData/Local/Temp/magick-ZsQSfEM-CFt6Gr4NZ7mUFFR2UbaYvaQr%d" "-fC:/Users/ADMINI~1/AppData/Local/Temp/magick-eT1ogBLBCjx3Tm4r2jidCDxbn3jmkZw6" "-fC:/Users/ADMINI~1/AppData/Local/Temp/magick-UaYBnaqm--_f0Gm6CSzMe8LnumhQQ16A"' (ϵͳ�Ҳ���ָ�����ļ���) @ error/delegate.c/ExternalDelegateCommand/516

阐明当初零碎没有 Ghostscript 软件,须要装置 Ghostscript。Ghostscript 是一套建基于 Adobe、PostScript 及可移植文档格局(PDF)的页面描述语言等而编译成的免费软件。Ghostscript 是 ImageMagick 的一个根底局部。
下载地址:https://ghostscript.com/relea…
能够下载 Ghostscript 9.55.0 for Windows (64 bit)版本。

至此,可能生成图片了。

2 调用百度智能云辨认文字

首先须要有百度的账号,注册就不说了,有了账号之后,还须要创立“利用”。
关上 https://cloud.baidu.com/produ…,抉择“产品”-》“人工智能”-》“OCR 文字辨认”上面的“通用场景文字辨认”。

而后,点击下图中的“立刻应用”。

而后点击下图中的“创立利用”。

填好信息之后,就会创立好一个利用,我创立的是“医案辨认”。

在上图中额 APIKey 和 Secret Key 就是咱们接下来须要用到的。

上代码:

def ocr_baidu(filename, access_token):
    # encoding:utf-8
    '''通用文字辨认'''
    request_url = "https://aip.baidubce.com/rest/2.0/ocr/v1/general_basic"
    # 二进制形式关上图片文件
    f = open(filename, 'rb')
    img = base64.b64encode(f.read())

    params = {"image": img}
    # access_token = '[调用鉴权接口获取的 token]'
    request_url = request_url + "?access_token=" + access_token
    headers = {'content-type': 'application/x-www-form-urlencoded'}
    response = requests.post(request_url, data=params, headers=headers)
    if response:
        # print(response.json())
        for words in response.json().get("words_result"):
        #     # print(words.get("words"))
            print(words)
        return response.json().get("words_result")
    else:
        return None

最初失去是一个 list 列表,外面放的是 words 为 key 的字典,如下图:

3 文字进行合并
比方外面的“编写阐明”应该是题目,第 2 - 3 个 value 值应该合并为一个段落。最好的办法应该是用 nlp 技术进行语义的辨认,这里就只简略做一下字符的判断了,不会太精确。
上代码:

def is_ChineseMarks(char):
    if char == "。" or char == "?" or char == "!" or char == "“" or char == ":":
        return True
    else:
        return False

def merge2txt(words_list, line_max_num=26, title_max_num=10):
    '''{'words':' 编写阐明 '}
    {'words': '《伤寒论》是汉代医学家张仲景所撰《伤寒杂病论》的一部分。'}
    {'words': '其理法为历代医家所遵循, 其方药为古今临床所惯用, 被尊为“方'}
    {'words': '书之祖”, 是祖国医学经典著作的重要一册。'}
    1. 题目:如果 words 对应字符串长度小于 title_max_num,且没有。号完结,则示意以后为题目。2. 段落:如果最初一个字符是。句号,且长度小于 line_max_num,则示意以后为段落。:param words_list:
    :param line_max_num:
    :param title_max_num:
    :return: 合并当前的文字内容
    '''txt =""
    for i in words_list:
        words = str(i.get("words"))
        if (not is_ChineseMarks(words[-1])) and len(words) <= title_max_num:
            txt += " " # 8 个空格
            txt += words
            txt += "\n"
        elif is_ChineseMarks(words[-1]) and len(words) <= line_max_num:
            txt += words
            txt += "\n"
            # txt += " " # 4 个空格,示意段首
        else:
            if txt.endswith("\n"):
                txt += " "# 4 个空格,示意段首
            txt += words

    return txt

调用百度的 ocr 服务,还须要 access_token,这个 access_token 是由后面的创立利用的 API Key 和 Secret key 来生成的。能够参考百度的文档:https://ai.baidu.com/ai-doc/R…

get_token()代码:

def get_token():
    # client_id 为官网获取的 AK,client_secret 为官网获取的 SK
    client_id = "用你的 API Key"
    client_secret = "用你的 Secret key"
    host = 'https://aip.baidubce.com/oauth/2.0/token?grant_type=client_credentials&client_id=' + client_id + '&client_secret=' + client_secret
    response = requests.get(host)
    # print(host)
    # print(response.content)
    if response:
        access_token = response.json().get("access_token")
    return access_token

上 main 函数:

if __name__ == "__main__":
    filename = "*****.pdf"
    # _run_convert(filename, 3)


    access_token = get_token()
    filename = "*****.png"
    words_list = ocr_baidu(filename, access_token)

    txt = merge2txt(words_list,26,10)
    print(txt)

合并后失去的后果大略是这样的:

原图是这样的:

能够看出,其实识别率还是有些问题。这里不狐疑百度的 ocr 识别率,其应该是国内成果最好的几家,关键问题可能还是 pdf 生成图片的时候的像素可能不够,导致图片不太清晰。这个问题的解决办法下一篇文章再写。

退出移动版