使用Hughlines变换进行角点检测

时间:2019-06-20 18:28:47

标签: python opencv hough-transform

我需要在给定图像上检测纸张的角。它始终将是整个图片的裁剪部分,仅包含一个角。我的想法是通过模糊和Canny边缘检测来变换图像以获取轮廓,然后使用Houghlines来获取角坐标。

但是我遇到了一些问题,实际上无法通过霍夫线连续,精确地检测到任何东西,而我的想法已经耗尽了。

我尝试过套牢而不是Canny,但是由于适用图像的许多变化,因此无法使用。我缩小了整个图像的尺寸,以使其更容易看到纸张的边缘,但仍然没有任何改善。线阈值的增加使纸张含量从纸质消失,但同时边线不时消失

输入 Input

边缘 Edge detection

结果 Results

要复制的代码

import cv2
import numpy as np

img = cv2.imread('inv_0001-01.1_0_corner.jpg')

resized = cv2.resize(img, (250,250), interpolation = cv2.INTER_AREA)
gray = cv2.cvtColor(resized, cv2.COLOR_BGR2GRAY)
kernel_size = 5
blur_gray = cv2.GaussianBlur(gray,(kernel_size, kernel_size),0)
edges = cv2.Canny(blur_gray,50,150,apertureSize = 3)

cv2.imshow('edges', edges)

cv2.waitKey()

min_line_length = 50  
max_line_gap = 20 

lines = cv2.HoughLinesP(edges, 1,  np.pi / 180, 5, np.array([]), min_line_length, max_line_gap)
for line in lines:
    for x1,y1,x2,y2 in line:
        cv2.line(resized,(x1,y1),(x2,y2),(255,0,0),5)

cv2.imshow('hough', resized)

cv2.waitKey()

我要去的结果是给定图像中纸角的坐标,但是在这篇文章中,我希望寻找一些帮助,以了解如何使用Houglines完成此类任务

1 个答案:

答案 0 :(得分:2)

此答案说明了如何找到角落。找到角落需要两部分解决方案。首先,需要将图像分为两个区域:纸张和背景。其次,您可以在分割的图像中寻找角落。

iamge2

找到边缘后,对图像进行填充以从背景中分割纸张(这是填充图像):

mask = np.zeros((h+2, w+2), np.uint8)
# Floodfill from point (0, 0)
cv2.floodFill(edges, mask, (0,0), 123);

现在您已经对图像进行了分割,请使用蒙版(这是标题为“ Masking”的图像)去除纸上的文字:

bg = np.zeros_like(edges)
bg[edges == 123] = 255

获得蒙版后,再次应用canny边缘过滤器以获取纸张的轮廓线(HoughLines需要轮廓而不是蒙版...这是“蒙版后的边缘”图像):

bg = cv2.blur(bg, (3,3))
edges = cv2.Canny(bg,50,150,apertureSize = 3)

现在,您可以在更清晰的图像上运行HoughLines算法。我使用的HoughLines算法与您使用的算法不同,但是您的算法也应该工作。这是我使用的完整代码:

import cv2
import numpy as np
import matplotlib.pyplot as plt
# Create a multi plot
f, axarr = plt.subplots(2,3, sharex=True)
img = cv2.imread('/home/stephen/Desktop/IRcCAWL.png')
resized = cv2.resize(img, (250,250), interpolation = cv2.INTER_AREA)
# Show source image
axarr[0,0].imshow(resized)
gray = cv2.cvtColor(resized, cv2.COLOR_BGR2GRAY)
kernel_size = 5
blur_gray = cv2.GaussianBlur(gray,(kernel_size, kernel_size),0)
edges = cv2.Canny(blur_gray,50,150,apertureSize = 3)
# Show first edges image
axarr[0,1].imshow(edges)
h, w = edges.shape[:2]
mask = np.zeros((h+2, w+2), np.uint8)
# Floodfill from point (0, 0)
cv2.floodFill(edges, mask, (0,0), 123);
# Show the flood fill image
axarr[0,2].imshow(edges)
floodfill = edges.copy()
bg = np.zeros_like(edges)
bg[edges == 123] = 255
# Show the masked image
axarr[1,0].imshow(bg)
bg = cv2.blur(bg, (3,3))
edges = cv2.Canny(bg,50,150,apertureSize = 3)
# Show the edges after masking
axarr[1,1].imshow(edges)

min_line_length = 50  
max_line_gap = 20

def intersection(line1, line2):
    """Finds the intersection of two lines given in Hesse normal form.
    Returns closest integer pixel locations.
    See https://stackoverflow.com/a/383527/5087436
    """
    rho1, theta1 = line1[0]
    rho2, theta2 = line2[0]
    A = np.array([
        [np.cos(theta1), np.sin(theta1)],
        [np.cos(theta2), np.sin(theta2)]
    ])
    b = np.array([[rho1], [rho2]])
    x0, y0 = np.linalg.solve(A, b)
    x0, y0 = int(np.round(x0)), int(np.round(y0))
    return [[x0, y0]]

import math
lines = cv2.HoughLines(edges, 1, np.pi / 180, 100, None, 0, 0)
# Draw the lines
if lines is not None:
    for i in range(0, len(lines)):
        rho = lines[i][0][0]
        theta = lines[i][0][1]
        a = math.cos(theta)
        b = math.sin(theta)
        x0 = a * rho
        y0 = b * rho
        pt1 = (int(x0 + 1000*(-b)), int(y0 + 1000*(a)))
        pt2 = (int(x0 - 1000*(-b)), int(y0 - 1000*(a)))
        cv2.line(resized, pt1, pt2, (123,234,123), 2, cv2.LINE_AA)

xy = tuple(intersection(lines[0], lines[1])[0])
resized = cv2.circle(resized, xy, 5, 255, 2)
# Show the image with the corner
axarr[1,2].imshow(resized)
# Add titles
axarr[0,0].set_title('Source Image')
axarr[0,1].set_title('Edges')
axarr[0,2].set_title('Floodfill')
axarr[1,0].set_title('Masking')
axarr[1,1].set_title('Edges after masking')
axarr[1,2].set_title('Hough Lines')
# Clean up
axarr[0,0].axis('off')
axarr[0,1].axis('off')
axarr[1,0].axis('off')
axarr[1,1].axis('off')
axarr[1,2].axis('off')
axarr[0,2].axis('off')
plt.show()
相关问题