寻找相似文档

5
我正在处理一个项目,其中有单页医疗报告和带标签类别的存储文档。用户将输入一个文档,我必须对其进行分类并确定属于哪个类别。
我已经将所有文档转换为灰度图像格式并存储以进行比较。
我有一个图像数据集,包含以下数据:
- `image_path`:该列具有图像路径 - `histogram_value`:该列具有图像的直方图,使用`cv2.calcHist`函数计算 - `np_avg`:该列具有图像所有像素的平均值。使用`np.average`计算 - `category`:该列是图像的类别。
我打算使用以下两种方法:
1. 计算输入图像的`histogram_value`,找到最近的10张匹配图像
- 计算输入图像的`np_avg`,找到最近的10张匹配图像 - 取两个结果集的交集 - 如果找到了多个图像,则进行模板匹配以找到最佳匹配。 我在图像处理领域知识很少。上述机制是否可靠?我查看了SO,在相同问题和期望结果的几个问题中发现了这个问题,看起来与我的情况类似,但它是非常通用的,我不确定它是否适用于我的情况。 样本报告链接

由于这些文档包含文本,如果您可以进行合理的OCR,则所获得的单词可能比像素值更好地用作特征。 - dhanushka
比较仅基于文本吗?报告中是否还包含图像?如果是,它们是否在每个报告中都一致出现? - amanb
@dhanushka,自己创建一个合理的OCR难度很大,你能否建议我一些开源解决方案可以使用?我尝试了tesseract,在我的情况下效果不佳。 - Gaurav Gandhi
@amanb,好主意。但我刚刚检查了一下,发现并非所有报告都有图像,而且某些图像适用于不同类别的报告。例如,来自同一实验室的报告在所有不同类别的报告中都有相同的标志。 - Gaurav Gandhi
1
可以分享一个虚拟报告吗?重要部分可以隐藏。另一个用于比较的报告也可能很有用。如果不是全部,只分享其中一部分也可以。 - amanb
显示剩余6条评论
3个回答

4
我建议以下几点:
基于文本的比较:
使用谷歌的Tesseract进行OCR文档并提取文本特征,这是目前最好的开源OCR软件之一。还有一个Python包装器 PyTesseract。您可能需要调整图像的分辨率才能使OCR满足您的要求 - 这将需要一些试错。
一旦提取了单词,通常认为的方法之一是计算TF-IDF(词频 - 逆文档频率),然后使用任何基于距离的方法(余弦相似性是其中常见的一种)来比较哪些文档“相似”(更接近)。
基于图像的比较:
如果您已经将图像作为向量,则可以应用基于距离的度量来确定相似性。通常L1或L2范数都可以工作。该paper表明曼哈顿(L1范数)在自然图像上可能效果更好。您可以从那里开始并尝试其他基于距离的度量。

文本和图像的集成比较

运行这两种方法,然后在两种方法之间进行一些平均处理,以得出相似的文档。

例如:

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

基于图像的方法可能会将DocC和DocB排名为最接近的两个文档,距离分别为5和20个单位。

然后可以对这两个距离进行平均。DocB将是(10+20)/2=15, DocC将是(20+5)/2=12.5个单位,因此在集成方法中,您将认为DocC比B更接近A。


我尝试使用文字或图像比较,但没有取得太大成功。我将尝试使用组合文字和图像比较。谢谢。 - Gaurav Gandhi
检查一下你的OCR质量。OCR工具在处理表格数据时会遇到困难,而在你的情况下可能有很多这样的数据。因此,在对其运行任何模型之前,专注于预处理OCR工具提取出来的内容,将其转化为合理的特征集。 - HakunaMaData

2
将文本翻译成中文:
测量文档相似性的复杂度从图像中比从文本中测量文档相似性高出两个原因。
  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方法,但仅使用CNN效果不佳。我会尝试这个方法的,谢谢。 - Gaurav Gandhi
感谢您详细的答案和代码示例。它比非神经网络方法效果更好,但仍需要很多改进。但现在这个商店已经开张了。谢谢。 - Gaurav Gandhi

1

样本文档差异很大,无法在图像水平(直方图、np_avg)上进行比较。

报告内容包括多个数值(最小值、最大值、推荐值)或类别结果(负面/正面)。

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

如果文档来源是数字化的(而非扫描),则需提取和比较字段、行。每一行单独处理。

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

如果文档被扫描,则需先处理图像旋转、质量和伪影问题,然后再进行提取。

每种类型的报告都是一个独立的问题。选择一种具有多个样本的报告开始。

由于涉及到数字,只有通过提取文本和数字才能获得良好的结果。如果报告显示值为 0.2,容许范围为 0.1 至 0.3,NN 不是处理该问题的工具。您必须比较数字。

NN 不是这方面的最佳工具,至少不适用于比较值。可能适用于部分提取过程。

解决方案步骤

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

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接