本文介绍了使用OpenCV检测表图像中的行和列数的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我们如何通过Opencv获取图像表中的行数和列数.

获取我正确的表格中的框的代码

 轮廓,层次结构= cv2.findContours(img_final_bin,cv2.RETR_TREE,cv2.CHAIN_APPROX_SIMPLE)def sort_contours(cnts,method ="left-to-right"):#初始化反向标志和排序索引反向=错误我= 0#处理是否需要反向排序如果方法==从右到左"或方法==从下到上":反向=真#处理是否根据y坐标而不是排序#边界框的x坐标如果method =="top-to-bottom"或method =="bottom-to-top":我= 1#构造边界框列表,并从上到下对其进行排序# 底部boundingBoxes = [c中以cts为单位的cv2.boundingRect(c)](cnts,boundingBoxes)= zip(* sorted(zip(cnts,boundingBoxes),key = lambda b:b [1] [i],reverse = reverse))#返回排序后的轮廓和边界框的列表返回(cnts,boundingBoxes)(轮廓,boundingBoxes)= sort_contours(轮廓,方法=自上而下") 
解决方案

这是一种可能的方法:

  1. 获取二进制图像.加载图像,转换为灰度,

    已删除文字轮廓+倒置图像

    这是在每个单元格中进行迭代以计算行数和列数的可视化视图

    结果

     行:7列数:4 

    代码

     将numpy导入为np从imutils导入轮廓导入cv2#加载图像,灰度,高斯模糊,大津的阈值图片= cv2.imread('1.jpg')灰色= cv2.cvtColor(图像,cv2.COLOR_BGR2GRAY)模糊= cv2.GaussianBlur(灰色,(5,5),0)阈值= cv2.threshold(模糊,0,255,cv2.THRESH_BINARY_INV + cv2.THRESH_OTSU)[1]#查找轮廓并删除单元格内的文本cnts = cv2.findContours(阈值,cv2.RETR_TREE,cv2.CHAIN_APPROX_SIMPLE)如果len(cnts)== 2,则cnts = cnts [0]否则,cnts [1]对于C中的cnts:面积= cv2.contourArea(c)如果面积<4000:cv2.drawContours(thresh,[c],-1,0,-1)#反转图片反转= 255-脱粒偏移量,old_cY,first = 10,0,True可视化= cv2.cvtColor(invert,cv2.COLOR_GRAY2BGR)#查找轮廓,从上到下排序,然后汇总列/行cnts = cv2.findContours(invert,cv2.RETR_TREE,cv2.CHAIN_APPROX_SIMPLE)如果len(cnts)== 2,则cnts = cnts [0]否则,cnts [1](cnts,_)= outlines.sort_contours(cnts,method ="top-to-bottom")对于C中的cnts:#查找质心M = cv2.moments(c)cX = int(M ["m10"]/M ["m00"])cY = int(M ["m01"]/M ["m00"])#新行如果(abs(cY)-abs(old_cY))>抵消:如果首先:行,表格= [],[]第一=错误old_cY = cYtable.append(行)行= []#同一行中的单元格如果((abs(cY)-abs(old_cY))< =偏移量)或第一个:row.append(1)#取消可视化注释'''cv2.circle(可视化,(cX,cY),10,(36,255,12),-1)cv2.imshow('可视化',可视化)cv2.waitKey(200)'''print('Rows:{}'.format(len(table)))print('Columns:{}'.format(len(table [1])))cv2.imshow('invert',invert)cv2.imshow('thresh',thresh)cv2.waitKey() 

    How can we get the number of rows and columns in an Image table via Opencv.

    Code for getting boxes in table which I am getting right

    contours, hierarchy = cv2.findContours(img_final_bin, cv2.RETR_TREE, cv2.CHAIN_APPROX_SIMPLE)
    
    def sort_contours(cnts, method="left-to-right"):
    # initialize the reverse flag and sort index
    reverse = False
    i = 0
    # handle if we need to sort in reverse
    if method == "right-to-left" or method == "bottom-to-top":
        reverse = True
    # handle if we are sorting against the y-coordinate rather than
    # the x-coordinate of the bounding box
    if method == "top-to-bottom" or method == "bottom-to-top":
        i = 1
    # construct the list of bounding boxes and sort them from top to
    # bottom
    boundingBoxes = [cv2.boundingRect(c) for c in cnts]
    (cnts, boundingBoxes) = zip(*sorted(zip(cnts, boundingBoxes),
        key=lambda b:b[1][i], reverse=reverse))
    # return the list of sorted contours and bounding boxes
    return (cnts, boundingBoxes)
    
    (contours, boundingBoxes) = sort_contours(contours, method="top-to-bottom")
    
    解决方案

    Here's a potential approach:

    1. Obtain binary image. Load image, convert to grayscale, Gaussian blur, then Otsu's threshold.

    2. Remove text inside cells. Find contours and filter using cv2.contourArea to remove text by filling in the contours with cv2.drawContours

    3. Invert image. We invert the image so the cells are in white and the background in black

    4. Sort cells and sum rows/columns. We find contours then sort the contours from top-to-bottom using imutils.contours.sort_contours. Next we iterate through contours and find the centroid to obtain the (cX, cY) coordinates. The idea is that we can compare the cY value of each cell to determine if it is a new row or a cell in the same row by using a offset. A cell should be in the same row if the cY value is +/- some offset value. If it is greater then it means the cell is in a new row. We build a model table where the length of the table gives you the rows while the length of any index gives you the number of columns.


    Binary image

    Removed text contours + inverted image

    Here's a visualization of iterating through each cell to count the number of rows and columns

    Result

    Rows: 7
    Columns: 4
    

    Code

    import numpy as np
    from imutils import contours
    import cv2
    
    # Load image, grayscale, Gaussian blur, Otsu's threshold
    image = cv2.imread('1.jpg')
    gray = cv2.cvtColor(image, cv2.COLOR_BGR2GRAY)
    blur = cv2.GaussianBlur(gray, (5,5), 0)
    thresh = cv2.threshold(blur, 0, 255, cv2.THRESH_BINARY_INV + cv2.THRESH_OTSU)[1]
    
    # Find contours and remove text inside cells
    cnts = cv2.findContours(thresh, cv2.RETR_TREE, cv2.CHAIN_APPROX_SIMPLE)
    cnts = cnts[0] if len(cnts) == 2 else cnts[1]
    for c in cnts:
        area = cv2.contourArea(c)
        if area < 4000:
            cv2.drawContours(thresh, [c], -1, 0, -1)
    
    # Invert image
    invert = 255 - thresh
    offset, old_cY, first = 10, 0, True
    visualize = cv2.cvtColor(invert, cv2.COLOR_GRAY2BGR)
    
    # Find contours, sort from top-to-bottom and then sum up column/rows
    cnts = cv2.findContours(invert, cv2.RETR_TREE, cv2.CHAIN_APPROX_SIMPLE)
    cnts = cnts[0] if len(cnts) == 2 else cnts[1]
    (cnts, _) = contours.sort_contours(cnts, method="top-to-bottom")
    for c in cnts:
        # Find centroid
        M = cv2.moments(c)
        cX = int(M["m10"] / M["m00"])
        cY = int(M["m01"] / M["m00"])
    
        # New row
        if (abs(cY) - abs(old_cY)) > offset:
            if first:
                row, table = [], []
                first = False
            old_cY = cY
            table.append(row)
            row = []
    
        # Cell in same row
        if ((abs(cY) - abs(old_cY)) <= offset) or first:
            row.append(1)
    
        # Uncomment to visualize
        '''
        cv2.circle(visualize, (cX, cY), 10, (36, 255, 12), -1)
        cv2.imshow('visualize', visualize)
        cv2.waitKey(200)
        '''
    
    print('Rows: {}'.format(len(table)))
    print('Columns: {}'.format(len(table[1])))
    
    cv2.imshow('invert', invert)
    cv2.imshow('thresh', thresh)
    cv2.waitKey()
    

    这篇关于使用OpenCV检测表图像中的行和列数的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!

08-16 08:05