从表的图像中分割单元格

时间:2018-04-09 16:10:25

标签: python opencv

我必须使用python和OpenCV获取表格图像的内容。

图片如下,讲师详细信息表,讲师姓名,主题代码:

我需要获取每一行的文字。例如:

Table row image

我当前的实现(最多分割表的行)如下:

import cv2
import numpy as np

cropped_Image_Location = "/home/shakya/Desktop/Paramore/CM_bot/timeTableDetails/Cropped/"
segmentCount = 0

img = cv2.imread(cropped_Image_Location+"cropped_5.jpg")

edges = cv2.Canny(img,50,150,apertureSize = 3)
cv2.imwrite('edges-50-150.jpg',edges)
minLineLength = 100
lines = cv2.HoughLinesP(image=edges, rho=1, theta=np.pi/10, threshold=200, lines=np.array([]), minLineLength= minLineLength, maxLineGap=100)

a,b,c = lines.shape
for i in range(a):
    cv2.line(img, (lines[i][0][0], lines[i][0][1]), (lines[i][0][2], lines[i][0][3]), (0, 0, 255), 3, cv2.LINE_AA)

small = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)

kernel = cv2.getStructuringElement(cv2.MORPH_ELLIPSE, (3, 3))
grad = cv2.morphologyEx(small, cv2.MORPH_GRADIENT, kernel)

_, bw = cv2.threshold(grad, 0.0, 255.0, cv2.THRESH_BINARY | cv2.THRESH_OTSU)

kernel = cv2.getStructuringElement(cv2.MORPH_RECT, (9, 1))
connected = cv2.morphologyEx(bw, cv2.MORPH_CLOSE, kernel)
# using RETR_EXTERNAL instead of RETR_CCOMP
_,contours, hierarchy = cv2.findContours(connected.copy(), cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_NONE)

mask = np.zeros(bw.shape, dtype=np.uint8)

for idx in range(len(contours)):
    x, y, w, h = cv2.boundingRect(contours[idx])
    mask[y:y+h, x:x+w] = 0
    cv2.drawContours(mask, contours, idx, (255, 255, 255), -1)
    r = float(cv2.countNonZero(mask[y:y+h, x:x+w])) / (w * h)

    if r > 0.45 and w > 8 and h > 8:
        cv2.rectangle(small, (x, y), (x+w-1, y+h-1), (0, 255, 0), 1)
        crop_img = small[y:y + h, x:x + w]
        segmentCount = segmentCount + 1
        imageNumber = str(segmentCount)

        cv2.imwrite(cropped_Image_Location+"Lecturer_cropped_" + imageNumber+".jpg", crop_img)

cv2.imwrite(cropped_Image_Location+'lectureAll.jpg', small)

cv2.waitKey(0)
cv2.destroyAllWindows()

我被困在分裂一排的细胞。

2 个答案:

答案 0 :(得分:1)

目标是找到长度大于某个阈值的水平线。找到水平线后,您可以找到(x,y)线的位置来裁剪行。 你可以像这样处理图像

import numpy as np
import cv2

img = cv2.imread('D:\Libraries\Downloads\Capture.PNG')
# find edges in the image
edges = cv2.Laplacian(img, cv2.CV_8U)
# kernel used to remove vetical and small horizontal lines using erosion
kernel = np.zeros((5, 11), np.uint8)
kernel[2, :] = 1
eroded = cv2.morphologyEx(edges, cv2.MORPH_ERODE,
                          kernel)  # erode image to remove unwanted lines

# find (x,y) position of the horizontal lines
indices = np.nonzero(eroded)
# As indices contain all the points along horizontal line, so get unique rows only (indices[0] contains rows or y coordinate)
rows = np.unique(indices[0])
# now you have unique rows but edges are more than 1 pixel thick
# so remove lines which are near to each other using a certain threshold
filtered_rows = []
for ii in range(len(rows)):
    if ii == 0:
        filtered_rows.append(rows[ii])
    else:
        if np.abs(rows[ii] - rows[ii - 1]) >= 10:
            filtered_rows.append(rows[ii])

print(filtered_rows)
# crop first row of table
first_cropped_row = img[filtered_rows[0]:filtered_rows[1], :, :]

cv2.imshow('Image', eroded)
cv2.imshow('Cropped_Row', first_cropped_row)
cv2.waitKey(0)

您可以使用filtered_rows裁剪表格的行

UPDATE: python 3.6.8的工作代码 - 基于http://answers.opencv.org/question/198043/problem-using-morphologyex/?answer=198052#post-id-198052

修复

答案 1 :(得分:0)

首先使用轮廓识别所有方框。

https://docs.opencv.org/3.3.1/d4/d73/tutorial_py_contours_begin.html

然后得到每个盒子的时刻。

https://docs.opencv.org/3.1.0/dd/d49/tutorial_py_contour_features.html

然后你可以识别该行。矩表示轮廓区域的中间像素。 doc说对象质量的核心

然后检查具有相同x值的相同轮廓。或者在小范围内(你决定)

将投资回报率结合起来。你会有一排。