使用OpenCV Python和Hough变换进行线检测

时间:2018-10-15 11:47:41

标签: opencv opencv-python

我正在尝试使用Python OpenCV和Hough变换算法来检测表格行并从图像中提取完整表格。我需要具有每条线的所有坐标,以便以相同的比例绘制相同的表格。我了解理论,霍夫变换是如何工作的,并尝试在没有OpenCV的情况下实现它,但是在大图像上它非常慢。

这是示例OpenCV Hough Transfrom中的代码

import cv2
import numpy as np

img = cv2.imread('image1.jpg')
gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)
edges = cv2.Canny(gray, 50, 150, apertureSize=3)
cv2.imshow("image", edges)
cv2.waitKey(0)
minLineLength = 100
maxLineGap = 10
lines = cv2.HoughLinesP(edges, 1, np.pi / 180, 50, minLineLength, maxLineGap)
for line in lines:
    for x1, y1, x2, y2 in line:
        cv2.line(img, (x1, y1), (x2, y2), (0, 255, 0), 2)

cv2.imwrite('houghlines5.jpg', img)

Canny边缘检测返回图像Resulf of Canny edge detectione

但是检测结果是Resulf of Housh Transform

我不知道为什么Hough变换会留下表格的某些行。你能推荐一些事情吗?也许是从图像中提取表格的另一种方法?谢谢!

UPD。 原始图片original table needed to detect

2 个答案:

答案 0 :(得分:0)

我在文档中找到了。

for x1,y1,x2,y2 in lines[0]:
    cv2.line(img,(x1,y1),(x2,y2),(0,255,0),2)

我不确定lines的确切结构,但是我看到的示例仅在第一个lines[0]中进行迭代。也许您从for line in lines中得到了一些意想不到的行为。

答案 1 :(得分:0)

我认为您必须在执行HoughLinesP()之前准备好图像,例如去除文本,使用参数玩耍或扩大边缘等。但是,如果要提取不带文本的模板,则只需从该表格中绘制所有文本即可(通过搜索较小的轮廓并在轮廓上制作一个白色的覆盖边框),可以使您的生活更轻松。在示例代码中,我执行了三个步骤:第一步是不使用Hough制作模板,第二步使用HoughLines(),第三步使用HoughLinesP()。希望能有所帮助。干杯!

示例:

import cv2
import numpy as np

### MAKING TEMPLATE WITHOUT HOUGH

# Read the image and make a copy then transform it to gray colorspace,
# threshold the image and search for contours.
img = cv2.imread('tablelines.png')
res = img.copy()
gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)
_, thresh = cv2.threshold(gray,0,255,cv2.THRESH_BINARY_INV+cv2.THRESH_OTSU)
_, contours, hierarchy = cv2.findContours(thresh,cv2.RETR_TREE,cv2.CHAIN_APPROX_NONE)

# Iterate through contours and draw a slightly bigger white rectangle
# over the contours that are not big enough (the text) on the copy of the image.
for i in contours:
    cnt = cv2.contourArea(i)
    if cnt < 500:
        x,y,w,h = cv2.boundingRect(i)
        cv2.rectangle(res,(x-1,y-1),(x+w+1,y+h+1),(255,255,255),-1)

# Display the result. Note that the image is allready the template!
cv2.imshow('res', res)
cv2.waitKey(0)
cv2.destroyAllWindows()

# Optional count the rows and columns of the table
count = res.copy()
gray = cv2.cvtColor(count, cv2.COLOR_BGR2GRAY)
_, thresh = cv2.threshold(gray,0,255,cv2.THRESH_BINARY+cv2.THRESH_OTSU)
_, contours, hierarchy = cv2.findContours(thresh,cv2.RETR_TREE,cv2.CHAIN_APPROX_NONE)

check = []
for i in contours:
    cnt = cv2.contourArea(i)
    if 10000 > cnt > 10:
        cv2.drawContours(count, [i], 0, (255,255,0), 2)
        M = cv2.moments(i)
        cx = int(M['m10']/M['m00'])
        cy = int(M['m01']/M['m00'])
        check.append([cx, cy])

check.sort(key = lambda xy: xy[1])
columns = 1

for i in range(0, len(check)-1):
    if check[i+1][1] + 5 >= check[i][1] >= check[i+1][1] - 5:
        columns += 1
    else:
        break
print(columns)

check.sort(key = lambda tup: tup[0])
rows = 1
for i in range(0, len(check)-1):
    if check[i+1][0] + 5 >= check[i][0] >= check[i+1][0] - 5:
        rows += 1
    else:
        break
print('Columns: ',columns)
print('Roiws : ',rows)

cv2.imshow('res', count)
cv2.waitKey(0)
cv2.destroyAllWindows()



### LINES WITH HOUGHLINES()

# Convert the resulting image from previous step (no text) to gray colorspace.
res2 = img.copy()
gray = cv2.cvtColor(res, cv2.COLOR_BGR2GRAY)

# You can either use threshold or Canny edge for HoughLines().
_, thresh = cv2.threshold(gray,0,255,cv2.THRESH_BINARY_INV+cv2.THRESH_OTSU)
#edges = cv2.Canny(gray, 50, 150, apertureSize=3)

# Perform HoughLines tranform.  
lines = cv2.HoughLines(thresh,1,np.pi/180,200)
for line in lines:
    for rho,theta in line:
            a = np.cos(theta)
            b = np.sin(theta)
            x0 = a*rho
            y0 = b*rho
            x1 = int(x0 + 1000*(-b))
            y1 = int(y0 + 1000*(a))
            x2 = int(x0 - 1000*(-b))
            y2 = int(y0 - 1000*(a))

            cv2.line(res2,(x1,y1),(x2,y2),(0,0,255),2)

#Display the result.
cv2.imshow('res', res)
cv2.imshow('res2', res2)
cv2.waitKey(0)
cv2.destroyAllWindows()


### LINES WITH HOUGHLINESP()

# Convert the resulting image from first step (no text) to gray colorspace.
res3 = img.copy()
gray = cv2.cvtColor(res, cv2.COLOR_BGR2GRAY)

# Use Canny edge detection and dilate the edges for better result.
edges = cv2.Canny(gray, 50, 150, apertureSize=3)
kernel = np.ones((4,4),np.uint8)
dilation = cv2.dilate(edges,kernel,iterations = 1)

# Perform HoughLinesP tranform.  
minLineLength = 100
maxLineGap = 10
lines = cv2.HoughLinesP(dilation, 1, np.pi / 180, 50, minLineLength, maxLineGap)
for line in lines:
    for x1, y1, x2, y2 in line:
        cv2.line(res3, (x1, y1), (x2, y2), (0, 255, 0), 2)

#Display the result.
cv2.imwrite('h_res1.png', res)
cv2.imwrite('h_res2.png', res2)
cv2.imwrite('h_res3.png', res3)

cv2.imshow('res', res)
cv2.imshow('res2', res2)
cv2.imshow('res3', res3)
cv2.waitKey(0)
cv2.destroyAllWindows()

结果:

enter image description here

enter image description here

enter image description here

列:7

行:21