查找相似文档

时间:2018-12-24 06:59:54

标签: python numpy opencv document

我正在一个项目中,我具有带有标签类别的单页医学报告的流程和文档。用户将输入一个文档,我必须对它属于哪个类别进行分类。

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

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

  • image_path :此列包含图像的路径
  • histogram_value :此列具有使用cv2.calcHist函数计算的图像直方图
  • np_avg :此列具有图像所有像素的平均值。使用np.average计算
    • category:此列是图像的类别。

我打算使用这两种方法,

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

我对图像处理领域的知识很少。上述机制对我而言是否可靠?

我检查了SO,发现相同的问题很少,但是它们有一个非常不同的问题和期望的结果。 This question看起来与我的情况类似,但是它非常通用,并且我不确定它是否可以在我的情况下使用。

Link to sample reports

3 个答案:

答案 0 :(得分:3)

我会推荐一些东西:

基于文本的比较:

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

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

基于图像的比较

如果您已经将图像作为矢量,则应用基于距离的度量来找出相似性。通常,L1或L2规范会起作用。 paper暗示曼哈顿(L1范数)可能更适合自然图像。您可以从此开始,然后尝试其他基于距离的度量

汇总基于文本和图像的比较

运行两种方法,然后在两种方法之间求平均,以得出彼此相似的文档。

例如

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

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

然后您可以平均两个距离。 DocB将为(10 + 20)/ 2 = 15,而DocC将为(20 + 5)/ 2 = 12.5个单位(与DocA分开)。这样一来,您就可以采用综合方法将DocC设置为比A更接近A。

答案 1 :(得分: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"))

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

答案 2 :(得分:1)

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

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

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

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

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

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

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

由于您要处理数字,因此仅对文本和数字进行提取即可获得良好的效果。如果报告说该值为0.2,并且容许范围在0.1到0.3之间,那么NN并不是解决这个问题的工具。您必须比较数字。

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

解决步骤

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