Обнаружение и выделение линий на изображении

Я пытаюсь написать фрагмент кода, который может обнаруживать и изолировать прямые линии от изображения. Для этого я использую библиотеку opencv вместе с обнаружением границ Canny и преобразованием Hough. Пока я придумал следующее:

import numpy as np
import cv2

# Reading the image
img = cv2.imread('sudoku-original.jpg')
# Convert the image to grayscale
gray = cv2.cvtColor(img,cv2.COLOR_BGR2GRAY)
# Edge detection
edges = cv2.Canny(gray,50,150,apertureSize = 3)
# Line detection
lines = cv2.HoughLines(edges,1,np.pi/180,200)

for rho,theta in lines[0]:
    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(img,(x1,y1),(x2,y2),(0,0,255),2)

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

Теоретически этот фрагмент кода должен работать, но, к сожалению, это не так. На полученном изображении четко видно, что найдена только одна строка. Я не совсем понимаю, что я здесь делаю неправильно и почему он обнаруживает только одну конкретную строку. Может ли кто-нибудь решить проблему здесь?

введите здесь описание изображения


person Frederik Vanclooster    schedule 27.05.2019    source источник
comment
Он показывает только одну строку, потому что вы указываете отображать только первую обнаруженную строку — lines[0]. На самом деле это работает только из-за причуды в том, как OpenCV отображает типы данных из C++ в Python. Если вы правильно перебираете весь массив (как предлагает @teng, хотя и с модификацией, упомянутой в моем комментарии), он будет правильно визуализировать все обнаруженные строки. Теперь следующий вопрос: почему это не обнаруживает все строки?   -  person Dan Mašek    schedule 27.05.2019
comment
Поскольку вы не должны задавать несколько вопросов в одном сообщении с вопросом, я бы предложил изменить заголовок на что-то вроде «Почему это визуализирует только одну обнаруженную строку?». Затем создайте новый вопрос о том, почему он не обнаруживает все строки (включая исправленную петлю for).   -  person Dan Mašek    schedule 27.05.2019
comment
И сохраните изображение edges в файл и посмотрите на него — это должно дать вам хорошую подсказку, почему не найдена вторая слева строка. IIRC учебник выполняет адаптивный порог перед дальнейшей обработкой - непоследовательное освещение изображения определенно должно вызвать проблемы.   -  person Dan Mašek    schedule 27.05.2019


Ответы (1)


Несмотря на то, что учебник по преобразованию Хафа в opencv использует только один цикл, форма lines актуальна [None,1,2], поэтому, когда вы используете lines[0], вы получите только один элемент для rho и один элемент для theta, что даст вам только одну строку. поэтому я предлагаю использовать двойной цикл (ниже) или некоторую магию среза numpy, чтобы поддерживать использование только 1 цикла. Чтобы обнаружить всю сетку, как упоминалось в Dan Masek, вам нужно будет поиграть с логикой обнаружения границ. Возможно, посмотрите решение , использующий HoughLinesP.

for item in lines:
    for rho,theta in item:
        ...

введите здесь описание изображения

person pangyuteng    schedule 27.05.2019
comment
Кое-что исправил... Теперь показывает намного больше строк, но все равно не все... - person Frederik Vanclooster; 27.05.2019
comment
Этот второй цикл не нужен, подойдет простой rho, theta = item[0], так как этот внутренний список всегда будет иметь только один элемент (это особенность метода OpenCV для сопоставления между структурами данных C++ и Python). - person Dan Mašek; 27.05.2019
comment
Также было бы полезно некоторое объяснение того, что OP сделал неправильно, и почему следует использовать код, который вы показываете. Еще лучше, если вы покажете пример того, как выглядит lines. - person Dan Mašek; 27.05.2019
comment
@DanMašek подойдет. Спасибо за предложение. - person pangyuteng; 27.05.2019