使用python对表格图像中的内部表进行计数
我得到了一个图像(一个矩形的表格),它又被分成了一些内部表格。问题是使用python获取这些内部表的计数。有人能告诉我怎么做吗?检查下面的示例图像 图像示例使用python对表格图像中的内部表进行计数,python,Python,我得到了一个图像(一个矩形的表格),它又被分成了一些内部表格。问题是使用python获取这些内部表的计数。有人能告诉我怎么做吗?检查下面的示例图像 图像示例 我需要获得count=78个表您可以将图像转换为二进制,计算图像行上的像素强度之和,并计算其中的峰值,然后计算图像列上的像素强度之和,并计算其中的峰值。这是图像中水平线和垂直线的数量。然后N=(水平线的数量-1)*(垂直线的数量-1) 示例代码(使用and): 来自PIL导入映像的>> >>>将numpy作为np导入 >>>im=np.a
我需要获得count=78个表您可以将图像转换为二进制,计算图像行上的像素强度之和,并计算其中的峰值,然后计算图像列上的像素强度之和,并计算其中的峰值。这是图像中水平线和垂直线的数量。然后N=(水平线的数量-1)*(垂直线的数量-1) 示例代码(使用and): 来自PIL导入映像的
>>
>>>将numpy作为np导入
>>>im=np.array(Image.open('cJyt5.png')。convert('L'))
>>>阈值=np.直方图(im,2)[1][1]
>>>im2=im<阈值
>>>垂直线=总和(np.平均值(im2,轴=0)>0.5)
>>>水平线=总和(np.平均值(im2,轴=1)>0.5)
>>>(垂直线-1)*(水平线-1)
78
如果线条超过1像素厚,则需要稍微更改代码,以不考虑np.mean(…)>0.5
中的多个连续True
值
一个简单的技巧是做
sum(np.max(0,np.diff(np.mean(…)>0.5))
来计算从False
到True
的变化次数。(未经测试)我提出了一个适用于您的示例图像的解决方案,但我不能保证它适用于其他人,因为它未经测试,可能很脆弱
说明:
- PIL(
)pip安装枕
python main.py./path/to/grid.png
从集合导入计数器
从itertools导入dropwhile,groupby
导入系统
从PIL导入图像
def将_转换为_二进制(im):
#首先转换为8位值,然后转换为二进制值。
返回im.convert('L').point(如果v<255,则lambda v:0,否则为1,模式为1'))
定义第一个交点(像素2d):
#如果它只有一个像素值,它就是一个边框
返回下一个(dropwhile(lambda x:len(set(x))==1,像素2d))
def单元_相交(像素1d):
#计算非连续0的数量并减去1。
返回计数器([g[0]表示groupby中的g(像素1d)])[0]-1
def转置(lst):
返回列表(地图(列表,邮政编码(*lst)))
def重塑E2D(lst,尺寸):
为范围(0,len(lst),size)中的i返回[lst[i:i+size]
def main():
使用Image.open(sys.argv[1])作为img:
bin\u data=list(将\u转换为\u二进制(img).getdata())
断言(已排序(计数器(bin_数据).values())==
已排序(计数器(img.getdata()).values())
bin_lst=重塑2D(bin_数据,img.宽度)
水平=第一个交叉点(bin\u lst)
垂直=第一个交叉点(换位(本底))
打印(单元格相交(水平)*单元格相交(垂直))
如果uuuu name uuuuuu='\uuuuuuu main\uuuuuuu':
main()
@RRSS完成。现在请考虑投票/接受答案。谢谢感谢@fferri提供的sol。它可以在给定的图像和小比例图像上工作,但在大比例图像上无法工作,即使按照您的建议进行了少量更改。(大比例尺意味着图像是由相机实时拍摄的)哦,恐怕你的问题是关于在你的计算机生成的图像中用1像素粗线识别表格。您可以很容易地绕过该限制,但它肯定不适用于非直线非轴对齐线。对于来自摄影机的图像,我建议使用opencv,尤其是对输入图像应用hough变换。打开另一个问题,我将在那里回答。@RRSS请记住包含您要识别的图像的实际示例,即来自摄影机的图像。我在这一点上遇到了一些错误“断言(已排序(计数器(bin_数据)。值())==已排序(计数器(img.getdata())。值()”,它表示“断言错误”。该错误是否发生在示例图像中?如果在断言之前创建计数器并打印出内容,您会得到什么?这是我得到的:Counter({1:95882,0:7203})Counter({(255,255,255,255):95882,(218,220,221,255):7203})
>>> from PIL import Image
>>> import numpy as np
>>> im = np.array(Image.open('cJyt5.png').convert('L'))
>>> threshold = np.histogram(im, 2)[1][1]
>>> im2 = im < threshold
>>> vert_lines = sum(np.mean(im2, axis=0) > 0.5)
>>> horiz_lines = sum(np.mean(im2, axis=1) > 0.5)
>>> (vert_lines - 1) * (horiz_lines - 1)
78
from collections import Counter
from itertools import dropwhile, groupby
import sys
from PIL import Image
def convert_to_binary(im):
# first converts to 8-bit values, then to binary.
return im.convert('L').point(lambda v: 0 if v < 255 else 1, mode='1')
def first_intersection(pixels2d):
# if it only has one pixel value it's a border
return next(dropwhile(lambda x: len(set(x)) == 1, pixels2d))
def cells_intersected(pixels1d):
# count the number of non-consecutive 0s and subtracts 1.
return Counter([g[0] for g in groupby(pixels1d)])[0] - 1
def transpose(lst):
return list(map(list, zip(*lst)))
def reshape2d(lst, size):
return [lst[i:i + size] for i in range(0, len(lst), size)]
def main():
with Image.open(sys.argv[1]) as img:
bin_data = list(convert_to_binary(img).getdata())
assert(sorted(Counter(bin_data).values()) ==
sorted(Counter(img.getdata()).values()))
bin_lst = reshape2d(bin_data, img.width)
horizontal = first_intersection(bin_lst)
vertical = first_intersection(transpose(bin_lst))
print(cells_intersected(horizontal) * cells_intersected(vertical))
if __name__ == '__main__':
main()