Python:识别1d分布中的起伏模式

时间:2017-08-20 19:50:11

标签: python opencv numpy machine-learning classification

我的问题简要说明:给定Python中的1d分布,如何识别该分布中具有正弦波状起伏模式的区域?

我正在努力识别历史文档的页面扫描中的图像。这些图像在扫描中基本上总是全宽的(也就是说,它们基本上不与文本并置)。这让我相信最简单的解决方案是删除包含文本行的页面扫描区域。

使用以下代码段,可以将图像读入内存并从上到下测量图像中每行的聚合像素亮度,将输入图像转换为下图:

import matplotlib.mlab as mlab
import matplotlib.pyplot as plt
from scipy.ndimage import imread
import numpy as np
import sys

img = imread(sys.argv[1])
row_sums = list([(sum(r)/len(r)) for r in img ])

# the size of the returned array = size of row_sums input array
window_size = 150
running_average_y = np.convolve(row_sums, np.ones((window_size,))/window_size, mode='same')

# plot the y dimension pixel distribution
plt.plot(running_average_y)
plt.show()

输入图片:

enter image description here

输出图:

enter image description here

鉴于这种分布,我现在想要确定曲线的区域,这些区域具有在图的第一个和最后三分之一中看到的规则起伏模式(粗略地说)。其他人是否有关于如何处理这项任务的想法?

起初我尝试将线性模型拟合到整个1d分布,但由于种种原因而失败。我现在认为尝试将类似正弦波的东西放到曲线的某些部分可能是有意义的,但这看起来有点矫枉过正。其他人是否有关于如何最好地完成这项任务的想法?任何建议或见解都将非常感激!

1 个答案:

答案 0 :(得分:5)

这不能回答你的问题,但也许可以解决你的问题。 平滑行和可以隐藏图像中的文本行被白色空间很好地分隔的事实 - 正如可移动类型打印所期望的那样。

您可以使用空格作为分隔符将图像分区为块。在大多数情况下,块对应于单线。非常大的块对应于图像。

enter image description here

import sys
import numpy as np
import matplotlib.pyplot as plt

MIN_BLOCK_SIZE = 100 # pixels

img = plt.imread(sys.argv[1])

# find blank rows
row_sums = np.mean(img, axis=1)
threshold = np.percentile(row_sums, 75)
is_blank = row_sums > threshold

# find blocks between blank rows
block_edges = np.diff(is_blank.astype(np.int))
starts, = np.where(block_edges == -1)
stops, = np.where(block_edges == 1)
blocks = np.c_[starts, stops]

# plot steps
fig, axes = plt.subplots(3,1, sharex=True, figsize=(6.85, 6))
axes[0].plot(row_sums)
axes[0].axhline(threshold, c='r', ls='--')
axes[1].plot(is_blank)
for (start, stop) in blocks:
    if stop - start > MIN_BLOCK_SIZE:
        axes[2].axvspan(start, stop, facecolor='red')
plt.show()