6

我要做的是处理下面的考勤表,告诉我谁在场,谁不在 考勤表

我目前正在使用 matchTemplate 使用一个奇异的黑点,它可以找到所有填充的点(图像首先转换为灰度)。下图

点匹配

然后我操纵 matchPattern 数组并在 y 方向上大致获得每个数组的中心,我可以看到与失踪学生相对应的间隙在哪里。

我遇到的问题是,确保这种方式适用于完美输入,但我的目标是能够拍摄一张物理纸的照片并进行处理?注意:考勤表由我制作,因此可以根据需要进行更改/修改。

我附上了一个示例图像以匹配如下所示。 测试匹配 使用我目前的方法只是一场灾难(见下文)。现在我不知道从哪里开始我尝试修改阈值但超过 0.65 时找不到任何图像。 失败

import cv2
import numpy as np
from matplotlib import pyplot as plt

values = []
img_rgb = cv2.imread('/home/user/Downloads/input.png')
img_gray = cv2.cvtColor(img_rgb, cv2.COLOR_BGR2GRAY)
template = cv2.imread('/home/user/Downloads/input_2.png',0)
w, h = template.shape[::-1]

res = cv2.matchTemplate(img_gray,template,cv2.TM_CCOEFF_NORMED)
threshold = 0.6
loc = np.where( res >= threshold)
for pt in zip(*loc[::-1]):
  cv2.rectangle(img_rgb, pt, (pt[0] + w, pt[1] + h), (0,0,255), 2)
  values.append(pt[1]+h/2)

cv2.imwrite('output.png',img_rgb)
values.sort()
pivot = values[0]
count = 1
total = values[0]
cleaned = []

for x in range(1,len(values)):
  if(values[x] < pivot+20):
    pivot = values[x]
    count = count + 1
    total = total + values[x]
  else:
    print values[x]
    cleaned.append(int(total/count))
    pivot = values[x]
    count = 1
    total = values[x]

  if x == len(values)-1:
    cleaned.append(int(total/count))
print values
print cleaned

这是另一个测试图像: 在此处输入图像描述

4

2 回答 2

3

通常,在分析纸质表格时,页边距和表格角上的特殊标记用于识别有意义部分的比例和方向。例如,您可以在表格的边框上打印几个黑色小方块,找到它们相同的地方cv2.matchTemplate,从而定义感兴趣的区域。

很可能您的表单不会被完美地捕获(例如,它们可能被缩放、旋转或透视),因此您还需要规范化输入。您可以为此使用透视或仿射变换

您可能还想通过使用直方图均衡去噪和其他技术来增强图像。

此时,您应该拥有更接近“完美输入”的完全标准化图像。您可以在此输入上尝试您的算法,但也有更简单的方法(AFAIK,类似的东西在实际应用程序中用于自动表单分析)。

您的表单具有固定的布局,并且您已经知道它的角落。那么为什么不计算表格中每个有趣部分的位置呢?例如,在下面的图片中,我在表格的角落放置了 4 个黑色地标。在标准化图像中,虚线区域的位置相对于这些地标总是相同的。

在此处输入图像描述

找出学生是否在听课就像将虚线区域分成固定的正方形区域(每个学生一个)一样简单,将该区域中的像素值相加并将该值与预定义的阈值进行比较。具有较低值的区域往往比白色更黑(学生参加了讲座),而具有较高值的​​区域最有可能是白色(学生缺席)。

所以,总结一下:

  1. 使用界标来定义纸的角。
  2. 针对这些地标对图像进行归一化。
  3. 如果需要,增强图像。
  4. 计算感兴趣区域的位置。
  5. 确定区域是否更有可能是黑白相间的。
于 2013-09-10T15:44:00.527 回答
3

这是一个如何使用相当简单的方法识别点的示例:

from skimage import io, color, filter, morphology, feature, img_as_float
from skimage.morphology import disk

image = io.imread('dots.jpg')

# Remove blue channel
bw = image.copy()
bw[..., 2] = 0

bw = 1 - img_as_float(color.rgb2gray(image))

big_mask = 150
small_mask = 10
min_dist = 50

bw = filter.rank.threshold_percentile(bw, disk(big_mask), p0=0.95)
bw = morphology.erosion(bw, disk(small_mask))

peaks = feature.corner_peaks(bw, min_distance=min_dist, indices=True)

import matplotlib.pyplot as plt
f, (ax0, ax1) = plt.subplots(1, 2)

ax0.imshow(image, cmap=plt.cm.gray)
ax1.imshow(bw, cmap=plt.cm.gray)
ax0.scatter(peaks[:, 1], peaks[:, 0], c='red', s=30)

plt.show()

检测到的点

于 2013-09-18T21:03:14.930 回答