Обнаружение углов с преобразованием Хьюлайнса - PullRequest
0 голосов
/ 20 июня 2019

Мне нужно определить угол листа бумаги по заданному изображению. Это всегда будет обрезанная часть целого изображения, содержащая только один из углов. Моя идея состояла в том, чтобы трансформировать изображение путем размытия и обнаружения краев Канни, чтобы получить контуры, а затем применить линии Houghlines, чтобы получить координаты угла.

Однако у меня возникает проблема с тем, чтобы действительно что-то последовательно и точно определять по линиям Хафа, и у меня заканчиваются идеи, что может быть причиной здесь.

Я попробовал трешолдинг вместо Canny, но он не сработает из-за большого количества вариаций в применимых изображениях. Я уменьшил изображение целиком, чтобы было легче видеть только края бумаги, но все еще без улучшений. Увеличение пороговых значений линий приводит к тому, что линии от содержимого бумаги исчезают, но в то же время линии краев время от времени исчезают

Input 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()

Моим результатом будет координата угла бумаги на данном изображении, но в этом посте я скорее ищу некоторую помощь в понимании того, как использовать Хуглина для таких задач

1 Ответ

2 голосов
/ 20 июня 2019

Этот ответ объясняет, как найти угол.Нахождение угла требует решения, состоящего из двух частей.Во-первых, изображение должно быть разделено на две области: бумага и фон.Во-вторых, вы можете искать углы в сегментированном изображении.

iamge2

После того, как вы найдете края, заполните изображение, чтобы отделить бумагу от фона (это изображение заливки):

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

Теперь, когда вы сегментировали изображение, избавьтесь от текста на бумаге с помощью маски (это изображение под названием «Маскировка»):

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

После того, как вы получите маску, снова примените фильтр canny edge, чтобы получить линию выхода бумаги (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()
...