opencv 对扫描图像中每行的阴影单元进行计数

ffdz8vbo  于 2023-04-12  发布在  其他
关注(0)|答案(2)|浏览(186)

我的主要使命是计算每一行中有阴影线的单元格的数量。
每个单元格代表5分钟,每行代表一个操作。

**预期输出可能是一个一维或二维列表,包含网格中的所有行以及每行上阴影单元格的数量。**我根据行号知道操作的名称。其他文档将有其他行的阴影。

但是我在使命1中遇到了困难,为了迭代每个单元格,我想当我有了网格时,我可以检查轮廓是否主要包含黑色或白色,从而捕捉到阴影。
到目前为止,我已经成功导入了pdf,对图像进行了纠偏和裁剪,因此只剩下有趣的部分。x1c 0d1x
阴影单元格上方的数字是无关紧要的,只是噪音。这只是许多文档中的一个,我估计书面数字可以到处显示。

此图像中的第12行具有29个阴影单元格= 2,42小时的操作工作

我认为我的面具工作可以改进,这是我到目前为止所做的:

image = cv2.imread('result.jpg')
gray = cv2.cvtColor(image,cv2.COLOR_BGR2GRAY)
se=cv2.getStructuringElement(cv2.MORPH_RECT , (8,8))
bg=cv2.morphologyEx(gray, cv2.MORPH_DILATE, se)
out_gray=cv2.divide(gray, bg, scale=255)

thresh = cv2.threshold(out_gray, 0, 255, cv2.THRESH_BINARY_INV + cv2.THRESH_OTSU)[1]

blur = cv2.GaussianBlur(thresh,(5,5),0)
kernel = np.ones((3, 3), np.uint8)
mask = cv2.erode(blur, kernel, iterations=2)

留给我这个:

我试过Canny和HoughLines,结果只捕捉到了网格的左侧,或者使整个图像充满了红线。
我试过this answer,它有两种方法来计算网格中的行和列。我已经很接近了,但还没有弄清楚如何忽略橡皮擦标记,并处理网格的“不一致性”。当迭代时,很难跟踪我在哪里。

也许这里有一个更好的方法是绘制/创建一个具有正确数量列的完美行。例如,复制第3行,然后复制并偏移x次。我不知道如何实现这一点。如果有趣的话,我可以分享更多我的尝试,但我已经撞了3个晚上,希望你们有更好的方法来解决这个问题?
任何帮助赞赏。

bfnvny8b

bfnvny8b1#

**免责声明:**这不是100%准确的解决方案:它仅适用于provided image,并且它错误地将一些具有阴影线的数字的单元格标记为阴影线。

脚本的输出是每行中阴影线单元格的计数:

[0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 29, 91, 104, 6, 25, 28, 0, 0, 0, 0, 0, 12, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]

为了便于说明,我用红色填充了所有阴影单元格:

验证码:

from PIL import Image, ImageDraw

CELL_WIDTH = 21
CELL_HEIGHT = 37
BLACK_PIXELS_THRESHOLD = CELL_WIDTH*CELL_HEIGHT*0.5

def find_hatched_cells(path_to_image):
    results = []
    hatched_cells = 0
    image = Image.open(path_to_image)
    thresh = 200
    fn = lambda x: 255 if x > thresh else 0
    image_bnw = image.convert('L').point(fn, mode='1')
    pixels = image_bnw.load()
    x_max, y_max = image.size
    column = 0
    row = 0
    offset_x = 0
    offset_y = 0
    draw = ImageDraw.Draw(image)
    while True:
        if row == 0:
            offset_y = 9
        elif row % 7 == 0:
            offset_y -= 1
        elif row % 34 == 0:
            offset_y += 9
        else:
            offset_y += 3
        y = offset_y + row * CELL_HEIGHT
        if y+CELL_HEIGHT > y_max:
            break
        while True:
            if column == 0:
                offset_x += 8
            elif column % 14 == 0:
                offset_x += 5
            elif column % 6 == 0:
                offset_x += 5
            else:
                offset_x += 3
            x = offset_x + column * CELL_WIDTH
            if x+CELL_WIDTH > x_max:
                column = 0
                offset_x = 0
                results.append(hatched_cells)
                hatched_cells = 0
                break
            fill = None
            if is_cell_hatched(pixels, x, y):
                hatched_cells += 1
                fill = 'red'
            draw.rectangle(((x, y), (x + CELL_WIDTH, y + CELL_HEIGHT)), outline='red', fill=fill)
            column += 1
        row += 1

    image.save('output.jpg')
    return results

def is_cell_hatched(pixels, x_start, y_start):
    """ Return True if cell is hatched, None if not hatched """
    black_pixels = 0
    for x in range(x_start, x_start + CELL_WIDTH, 1):
        for y in range(y_start, y_start + CELL_HEIGHT, 1):
            if pixels[x, y] == 0:
                black_pixels += 1
                if black_pixels > BLACK_PIXELS_THRESHOLD:
                    return True

print(find_hatched_cells('image.jpg'))
olhwl3o2

olhwl3o22#

我绝望了,检查了Bing AI Copilot。在我问了几个后续问题后,它写了一个相当不错的代码。独立的行和单元格尺寸,忽略计算列数较少的行。我不敢发布它,因为我看到提到Stacked对AI答案是否定的。尽管如此,我还是做了一些自己的调整。

相关问题