Обнаружение почти прямых линий с помощью OpenCv в Python

Я обнаруживаю прямые линии на изображении с помощью OpenCv. Ниже приведен код:

import cv2
import numpy as np

img = cv2.imread('Image.jpg')
img = img[:, 10:img.shape[1]-10]
gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)
edges = cv2.Canny(gray, 50, 150, apertureSize=3)
minLineLength = img.shape[1] - 300
lines = cv2.HoughLinesP(image=edges, rho=0.02, theta=np.pi / 500, threshold=10, lines=np.array([]), minLineLength=minLineLength, maxLineGap=2)
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), 2, cv2.LINE_AA)
cv2.imwrite('result.png', img)

Для изображения (Снимок экрана PDF) Image.jpg(Ниже) я получаю result.png( Ниже), и это именно тот результат, который мне нужен.

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

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

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

a, b, c = lines.shape # 10th Line
AttributeError: 'NoneType' object has no attribute 'shape'

Я думаю, потому что в Test.jpg горизонтальные линии не такие прямые (потому что я нажал на это камерой телефона), а также если я изменю minLineLength значение, скажем, 100, оно не показывает вышеуказанную ошибку, но показывает неполные блеклые линии в каждой строке . Так может ли кто-нибудь сказать мне, какие параметры я должен изменить в своем алгоритме, чтобы он работал правильно?

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


person Aadit    schedule 16.04.2018    source источник
comment
Во-первых, что означает ваш комментарий на 10-й строке? Вы взяли размеры возвращенного вектора линий. Судя по сообщению об ошибке, в этот момент lines равно None. Я нахожу это очень странным: увеличение порога должно уменьшить количество строк, а не позволить найти их там, где меньшее значение не дало ни одной. Проверьте это значение lines и перепроверьте аргументы, которые вы даете этому вызову.   -  person Prune    schedule 17.04.2018
comment
эта ошибка находится в 10-й строке опубликованного кода. Изменяя minLineLength, я хотел извиниться. Посмотрите еще раз на вопрос. @Чернослив   -  person Aadit    schedule 17.04.2018


Ответы (2)


Вам нужно ослабить ваше определение "прямой". Документация понятна, если вы уже знакомы с терминологией геометрии. «ро» и «тета» - это переменные для полярных координат: в данном случае длины и направления. Поскольку вас беспокоит изменение направления, вам нужно ослабить тета-значение.

theta=np.pi / 500

Слишком ограничительный (PI/500 радиан, чуть более 1/3 градуса). Уменьшайте эту цифру на 500, пока не получите желаемый результат. Например, попробуйте начать с 90 (1 градус).

person Prune    schedule 16.04.2018
comment
Я прошел через это. следующая ошибка каждый раз: a, b, c = lines.shape, AttributeError: объект «NoneType» не имеет атрибута «shape» @Prune - person Aadit; 16.04.2018
comment
Вы проходите разумный учебник; спасибо за ссылку. Однако мы мало что можем сделать для устранения ошибки, пока вы не опубликуете вспомогательный код на свой вопрос. Вы действительно получили это, просто изменив знаменатель выражения theta? - person Prune; 16.04.2018
comment
Рад помочь. На самом деле я должен был упомянуть, что эта ошибка была выдана ранее, когда я пробовал Test.jpg в качестве входных данных, а также если я изменил параметр minLength на какое-то произвольное значение, скажем, 100, он показывает неполные блеклые строки в каждой строке. PS: я использую указанный код в своем вопросе, чтобы проверить это изображение. @Чернослив - person Aadit; 16.04.2018
comment
Пожалуйста, обновите свое сообщение, чтобы уточнить, когда вы получаете ошибку, а когда нет. Очевидно, вы получили хороший результат (для действительно прямых линий) по крайней мере один раз. - person Prune; 17.04.2018
comment
Обычно я думаю, что увеличение theta и уменьшение threshold улучшит ваши результаты. Если у вас возникли проблемы с длиной строки, поэкспериментируйте также с rho -- я думаю, что вы хотите увеличить ее, но не уверен насчет внутреннего алгоритма. - person Prune; 17.04.2018
comment
Давайте продолжим обсуждение в чате. - person Aadit; 17.04.2018

возможно, добавьте условие для проверки наличия строки. помните, что вы ищете строки определенной длины. на втором изображении нет. я попробовал ваш код и прокомментировал

minLineLength = img.shape[1] - 300

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

#img = img[:, 10:img.shape[1]-10]
minLineLength = 10 #img.shape[1] - 300

это работает, если это так, окончательный код, который я выполнил,

import cv2
import numpy as np
img = cv2.imread('test.jpg')
#img = img[:, 10:img.shape[1]-10]
gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)
edges = cv2.Canny(gray, 50, 150, apertureSize=3)
minLineLength = 20 #img.shape[1] - 300
lines = cv2.HoughLinesP(image=edges, rho=0.02, theta=np.pi / 500,     threshold=10, lines=np.array([]), minLineLength=minLineLength, maxLineGap=2)
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), 2, cv2.LINE_AA)
cv2.imwrite('result.png', img)
person kishea    schedule 17.04.2018
comment
это то, что я упомянул в самом своем вопросе. Как я уже сказал, примите minLineLength равным 100. Это дает лучшие результаты, чем ваш код, но строки все еще неполные и блеклые. - person Aadit; 17.04.2018