【问题标题】:Finding Similar Document查找类似文档
【发布时间】:2019-05-23 10:14:03
【问题描述】:

我正在从事一个项目,在该项目中,我处理并存储了带有标签类别的单页医疗报告的文档。用户将输入一个文档,我必须对其所属的类别进行分类。

我已将所有文档转换为灰度图像格式并存储以供比较。

我有一个包含以下数据的图像数据集,

  • image_path:此列有图片路径
  • histogram_value:此列有图片的直方图,使用cv2.calcHist函数计算得出
  • np_avg:该列有图像所有像素的平均值。使用np.average 计算
    • category:此列是图片的一个类别。

我打算用这两种方法,

  • 计算输入图像的histogram_value,找到最接近的10个匹配图像
    • 计算输入图像的np_avg,找到最接近的10个匹配图像
    • 取两个结果集的交集
    • 如果找到多个图像,请进行模板匹配以找到最合适的图像。

我对图像处理领域知之甚少。上述机制对我的目的是否可靠?

我检查了 SO,发现很少有相同的问题,但它们的问题和期望的结果非常不同。 This question 看起来与我的情况相似,但它非常通用,我不确定它是否适用于我的场景。

Link to sample reports

【问题讨论】:

  • 由于这些是包含文本的文档,如果您可以进行合理的 OCR,那么由此获得的单词可能会作为比像素值更好的特征。
  • 比较是否仅基于文本?报告是否也包含任何图像?如果是,它们是否始终出现在每份报告中?
  • @dhanushka,合理的 OCR 很难由我自己创建,你能建议我一些我可以使用的开源解决方案吗?我尝试了 tesseract,但在我的情况下效果不佳。
  • @amanb,好主意。但我刚刚检查并发现图像并非在所有报告中,而且一些图像对于不同类别的报告是常见的。例如,来自同一实验室的报告在所有不同类别的报告中都有相同的徽标。
  • 是否可以共享虚拟报告?可以隐藏重要部分。另一个用于比较的报告也可能有用。如果不是全部,只是其中的一部分。

标签: python numpy opencv document


【解决方案1】:

与从文本中测量文档相比,从图像中测量文档的相似度比较复杂,原因有两个。

  1. 图像在亮度、文本上下文、图表或符号方面可能具有相似性。
  2. 与文本信息相比,通常更难从文档包含的图像中找到文档的表示。

解决方案

我的解决方案是使用机器学习来查找文档的表示并使用此表示对文档进行分类。 在这里,我将给出我提出的解决方案的 Keras 实现。

网络类型

我建议使用卷积层进行特征提取,然后使用循环层进行序列分类。我选择 keras 是因为我很熟悉,它有简单的 API 来定义一个包含卷积层和循环层组合的网络。但是代码可以很方便的改成其他库,比如Pytorch、Tensorflow等。

图像预处理

有很多方法可以为神经网络预处理文档图像。我在做假设。

  • 图像包含水平文本而不是垂直文本。
  • 文档图像大小是固定的。如果图像大小不固定,可以使用opencv's resize 方法调整大小。

垂直分割图像,以便将行作为序列馈送(如果分割线可以在空行上进行,则效率更高)。我将使用 Numpy 对单个文档进行展示。在下面的实现中,我假设单个文档的图像形状为 (100, 100, 3)。 首先,让我们定义 image_shape 文档图像的形状为

import numpy as np
image_shape = (100, 100, 3)
split_size = 25 # this should be factor of the image_shape[0]
doc_images = [] #
doc_image = np.zeros(image_shape)

splitted_images = np.split(doc_image,[split_size], axis=0)
doc_images.extend(splitted_images)
doc_images = np.array(doc_images)

网络实现

Keras 有ConvLSTM2D 层来处理连续图像。网络的输入是通过拆分文档图像生成的一系列图像列表。

from keras.models import Sequential
from keras.layers import ConvLSTM2D, Dense, Flatten
num_of_classes = 10
model = Sequential()

model.add(ConvLSTM2D(32,(3, 3),input_shape=(None, split_size, image_shape[1],image_shape[2]),
        padding='same',
        return_sequences=True))
model.add(ConvLSTM2D(32,(3, 3),padding='same',return_sequences=True))
model.add(ConvLSTM2D(32,(3, 3),padding='same',return_sequences=False))
model.add(Flatten())
model.add(Dense(1024, activation="relu"))
model.add(Dense(num_classes, activation="softmax"))

理想情况下,该模型可以工作,因为该模型可能会从其图像中学习文档的层次表示(字符、单词、句子、上下文、符号)。

【讨论】:

  • 我没有尝试过 RNN 方法,但 Just CNN 效果不佳。我会试一试,谢谢。
  • 感谢您提供代码示例的详细回答。它比不使用 NN 方法效果更好,仍然需要很多改进。但是现在这家商店已经航行了。谢谢。
【解决方案2】:

示例文档差异很大,无法在图像级别(直方图,np_avg)进行比较。

报告的内容是多个数字(最小、最大、推荐)或类别结果(负/正)。

对于每种类型的报告,您必须进行预处理。

如果文档来源是数字的(未扫描),您可以提取和比较字段、行。每行分开。

  • 提取到图像部分的字段或行并将其与 NN 进行比较
  • 提取到文本并比较值 (OCR)

如果文档被扫描,您必须在提取之前处理图像、质量和伪影的旋转。

每种类型的报告都有其自身的问题。选择一种包含多个样本的报告类型作为开始。

由于您正在处理数字,因此只有提取到文本和数字才能获得良好的结果。如果报告说值为 0.2 并且容忍范围在 0.1 和 0.3 之间,则 NN 不是用于此目的的工具。你必须比较数字。

NNs 不是最好的工具,至少不是比较值。也许是提取过程的一部分。

解决步骤

  • 报告自动分类
  • 为每种类型的带有数据的报告标记字段
  • 为每种类型的报告自动提取值
  • 根据业务规则对每种类型的报告解释值

【讨论】:

    【解决方案3】:

    我会推荐一些东西:

    基于文本的比较:

    使用 Google 的 Tesseract 对文档进行 OCR 并提取文本特征,这是目前最好的开源 OCR 软件包之一。还有一个名为PyTesseract 的Python Wrapper。您可能需要调整图像的分辨率,才能让 OCR 满意 - 这需要反复试验。

    提取单词后,一种普遍接受的方法是计算 TF-IDF(词频 - 逆文档频率),然后使用任何基于距离的方法(余弦相似度是常见的方法之一)来比较哪些文档彼此“相似”(更接近)。

    基于图像的比较

    如果您已经将图像作为矢量,则应用基于距离的度量来计算相似度。通常 L1 或 L2 范数会起作用。这个paper 表明曼哈顿(L1 标准)可能更适合自然图像。你可以从那开始,然后尝试其他基于距离的度量

    基于整体文本和图像的比较

    运行这两种方法,然后在这两种方法之间取一些平均值,以获得彼此相似的文档。

    例如

    基于文本的方法可能会将 DocB 和 DocC 列为最接近 DocA 的 2 个文档,距离分别为 10 和 20 个单位。

    基于图像的方法可能会将 DocC 和 DocB 分别列为距离 5 和距离 20 最接近的两个。

    然后你可以平均这两个距离。 DocB 为 (10+20)/2 = 15,DocC 为 (20+5)/2 = 12.5 个单位,与 DocA 相距。因此,您将在集成方法中将 DocC 视为更接近 A 而不是 B。

    【讨论】:

    • 我尝试了基于文本或图像的比较,但没有取得很大成功,将尝试基于文本和图像的比较,谢谢。
    • 检查您的 OCR 有多好。 OCR 工具难以处理表格数据,在您的情况下,您可能会遇到很多问题。因此,在运行任何模型之前,请专注于将 OCR 工具为您提取的任何内容预处理为一组合理的特征。
    猜你喜欢
    • 1970-01-01
    • 2012-08-20
    • 2016-07-07
    • 2019-06-23
    • 1970-01-01
    • 2014-01-14
    • 2012-12-17
    • 1970-01-01
    • 2013-12-22
    相关资源
    最近更新 更多