查找相似文件
Finding Similar Document
我正在从事一个项目,在该项目中,我处理并存储了带有标签类别的单页医疗报告的文档。用户将输入一个文档,我必须对它属于哪个类别进行分类。
我已将所有文档转换为灰度图像格式并存储以供比较。
我有一个包含以下数据的图像数据集,
image_path
:这一栏有图片路径
histogram_value
:这一列有图像的直方图,使用cv2.calcHist
函数计算
np_avg
:这一列是图像所有像素的平均值。使用 np.average
计算
category
: 该列为图片的类别
我打算用这两种方法,
- 计算输入图像的
histogram_value
,找到最近的10张匹配图像
- 计算输入图像
np_avg
,找到最近的10张匹配图像
- 取两个结果集的交集
- 如果找到不止一张图片,请进行模板匹配以找到最合适的图片。
我对图像处理领域知之甚少。上述机制对我来说是否可靠?
我检查了 SO,发现了几个相同的问题,但他们有一个非常不同的问题和期望的结果。 This question 看起来与我的情况相似,但它非常通用,我不确定它是否适用于我的情况。
我会推荐一些东西:
基于文本的比较:
OCR 文档并使用 Google 的 Tesseract 提取文本特征,这是目前最好的开源 OCR 包之一。还有一个名为 PyTesseract 的 Python 包装器。您可能需要调整图像的分辨率才能使 OCR 达到您满意的效果 - 这需要反复试验。
提取单词后,一种普遍接受的方法是计算 TF-IDF(词频 - 逆文档频率),然后使用任何基于距离的方法(余弦相似度是一种常见的方法)进行比较哪些文档彼此 "similar"(更接近)。
基于图像的比较
如果您已经将图像作为矢量,则应用基于距离的度量来计算相似性。通常 L1 或 L2 范数都可以。 paper 表明曼哈顿(L1 范数)可能更适合自然图像。您可以从那开始并尝试其他基于距离的措施
基于集成文本和图像的比较
运行 这两种方法,然后在这两种方法之间取一些平均值以获得彼此相似的文档。
例如
基于文本的方法可能会将 DocB 和 DocC 列为最接近 DocA 的两个文档,距离分别为 10 和 20 个单位。
基于图像的方法可能会将 DocC 和 DocB 分别列为最接近距离 5 和距离 20 的两个。
然后你可以平均这两个距离。 DocB 将是 (10+20)/2 = 15,DocC 将是 (20+5)/2 = 12.5 个单位,与 DocA 相距。因此,在集成方法中,您会将 DocC 视为更接近 A 而不是 B。
与从文本中测量文档相比,从图像中测量文档的相似性更复杂,原因有二。
- 图像在亮度、文本上下文、图表或符号方面可能具有相似性。
- 与文本信息相比,从文档包含的图像中找到文档的表示通常更难。
解决方案
我的解决方案是使用机器学习来查找文档的表示,并使用该表示对文档进行分类。
这里我将我提出的解决方案给 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"))
理想情况下,该模型会起作用,因为该模型可能会从图像中学习文档的层次表示(字符、单词、句子、上下文、符号)。
样本文档差异很大,无法在图像级别(直方图,np_avg)进行比较。
报告的内容是多个数字(最小值、最大值、推荐值)或类别结果(Negative/Positive)。
对于每种类型的报告,您都必须进行预处理。
如果文档来源是数字的(不是扫描的),您可以提取和比较字段、行。每行分开。
- 提取字段或行的图像部分并与 NN 进行比较
- 文本提取和比较值 (OCR)
如果扫描文档,您必须在提取之前处理图像旋转、质量和伪影。
每种类型的报告都有其自身的问题。选择一种包含多个样本的报告作为开始。
由于您处理的是数字,因此仅提取文本和数字即可获得良好的结果。如果报告说值为 0.2 并且容忍范围在 0.1 和 0.3 之间,则 NN 不是该工具。你必须比较数字。
NN 不是最好的工具,至少不是比较值。也许是提取过程的一部分。
解决步骤
- 报告自动分类
- 为每种类型的报告标记字段数据
- 对于每种类型的报告自动提取值
- 对于每种类型的报告,根据业务规则解释值
我正在从事一个项目,在该项目中,我处理并存储了带有标签类别的单页医疗报告的文档。用户将输入一个文档,我必须对它属于哪个类别进行分类。
我已将所有文档转换为灰度图像格式并存储以供比较。
我有一个包含以下数据的图像数据集,
image_path
:这一栏有图片路径histogram_value
:这一列有图像的直方图,使用cv2.calcHist
函数计算np_avg
:这一列是图像所有像素的平均值。使用np.average
计算category
: 该列为图片的类别
我打算用这两种方法,
- 计算输入图像的
histogram_value
,找到最近的10张匹配图像- 计算输入图像
np_avg
,找到最近的10张匹配图像 - 取两个结果集的交集
- 如果找到不止一张图片,请进行模板匹配以找到最合适的图片。
- 计算输入图像
我对图像处理领域知之甚少。上述机制对我来说是否可靠?
我检查了 SO,发现了几个相同的问题,但他们有一个非常不同的问题和期望的结果。 This question 看起来与我的情况相似,但它非常通用,我不确定它是否适用于我的情况。
我会推荐一些东西:
基于文本的比较:
OCR 文档并使用 Google 的 Tesseract 提取文本特征,这是目前最好的开源 OCR 包之一。还有一个名为 PyTesseract 的 Python 包装器。您可能需要调整图像的分辨率才能使 OCR 达到您满意的效果 - 这需要反复试验。
提取单词后,一种普遍接受的方法是计算 TF-IDF(词频 - 逆文档频率),然后使用任何基于距离的方法(余弦相似度是一种常见的方法)进行比较哪些文档彼此 "similar"(更接近)。
基于图像的比较
如果您已经将图像作为矢量,则应用基于距离的度量来计算相似性。通常 L1 或 L2 范数都可以。 paper 表明曼哈顿(L1 范数)可能更适合自然图像。您可以从那开始并尝试其他基于距离的措施
基于集成文本和图像的比较
运行 这两种方法,然后在这两种方法之间取一些平均值以获得彼此相似的文档。
例如
基于文本的方法可能会将 DocB 和 DocC 列为最接近 DocA 的两个文档,距离分别为 10 和 20 个单位。
基于图像的方法可能会将 DocC 和 DocB 分别列为最接近距离 5 和距离 20 的两个。
然后你可以平均这两个距离。 DocB 将是 (10+20)/2 = 15,DocC 将是 (20+5)/2 = 12.5 个单位,与 DocA 相距。因此,在集成方法中,您会将 DocC 视为更接近 A 而不是 B。
与从文本中测量文档相比,从图像中测量文档的相似性更复杂,原因有二。
- 图像在亮度、文本上下文、图表或符号方面可能具有相似性。
- 与文本信息相比,从文档包含的图像中找到文档的表示通常更难。
解决方案
我的解决方案是使用机器学习来查找文档的表示,并使用该表示对文档进行分类。 这里我将我提出的解决方案给 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"))
理想情况下,该模型会起作用,因为该模型可能会从图像中学习文档的层次表示(字符、单词、句子、上下文、符号)。
样本文档差异很大,无法在图像级别(直方图,np_avg)进行比较。
报告的内容是多个数字(最小值、最大值、推荐值)或类别结果(Negative/Positive)。
对于每种类型的报告,您都必须进行预处理。
如果文档来源是数字的(不是扫描的),您可以提取和比较字段、行。每行分开。
- 提取字段或行的图像部分并与 NN 进行比较
- 文本提取和比较值 (OCR)
如果扫描文档,您必须在提取之前处理图像旋转、质量和伪影。
每种类型的报告都有其自身的问题。选择一种包含多个样本的报告作为开始。
由于您处理的是数字,因此仅提取文本和数字即可获得良好的结果。如果报告说值为 0.2 并且容忍范围在 0.1 和 0.3 之间,则 NN 不是该工具。你必须比较数字。
NN 不是最好的工具,至少不是比较值。也许是提取过程的一部分。
解决步骤
- 报告自动分类
- 为每种类型的报告标记字段数据
- 对于每种类型的报告自动提取值
- 对于每种类型的报告,根据业务规则解释值