Обнаружение линии OpenCV для линий 45 градусов - PullRequest
0 голосов
/ 27 ноября 2018

У меня есть изображение:

original image where opencv houghP transform can't find the -45 degree line

На этом изображении преобразование OpenCV Hough не может обнаружить большую линию -45 градусов, используя

minLineLength = 150 
maxLineGap = 5 
line_thr = 150 
linesP = cv.HoughLinesP(dst, 1, np.pi / 180, line_thr, None, minLineLength, maxLineGap) 

Единственные найденные строки:

lines found

Я также пытался играть с различными порогами, но не могу найти линию здесь,

Если я вручную обрежу изображение следующим образом:

cropped version where line is found

, тогда я ясно вижу преобразование OpenCV Hough, находящее правильную линию:

line found

Я хочу найти эту же строку в не обрезанной версии.Какие-нибудь предложения относительно не обрезанной версии, чтобы найти это?

Также могут быть случаи, когда линии вообще нет или линия не идет полностью для длины оси X.Примеры

enter image description here enter image description here

Ответы [ 4 ]

0 голосов
/ 29 ноября 2018

Ваш оригинальный код в порядке свистка.Единственная проблема состоит в том, что ваше изображение содержит слишком много информации, которая портит оценки аккумулятора.Все будет работать, если вы увеличите порог линии до 255.

minLineLength = 150 
maxLineGap = 5
line_thr = 255
linesP = cv2.HoughLinesP(dst, 1, np.pi / 180.0, line_thr, None, minLineLength, maxLineGap) 

Вот результаты, использующие это значение.Из-за большого размера белого пикселя здесь обнаруживаются 3 линии.

[  1  41 286 326]
[  0  42 208 250]
[  1  42 286 327]

enter image description here

5 линий обнаруживаются вокруг одной и той же области по той же причинекак указано выше.Уменьшение размера пикселей с помощью морфологической операции или преобразования расстояния должно исправить это.

[110 392 121 598]
[112 393 119 544]
[141 567 147 416]
[ 29 263  29 112]
[  0  93 179 272]

enter image description here

Здесь не найдено ни одной строки.enter image description here

0 голосов
/ 28 ноября 2018

Я реализовал немного более простой алгоритм, чем мой другой ответ, но в Python с OpenCV на этот раз.

По сути, вместо того, чтобы брать среднее значение вертикальных столбцов пикселей, он суммирует пикселив столбцах и выбирает столбец, который является самым ярким.Если я покажу дополненное, повернутое изображение с другим изображением ниже, представляющим суммы столбцов, вы должны увидеть, как оно работает:

enter image description here

#!/usr/bin/env python3

import cv2
import numpy as np

# Load image as greyscale
im = cv2.imread('45.jpg',cv2.IMREAD_GRAYSCALE)

# Pad with border so it isn't cropped when rotated
bw=300
bordered = cv2.copyMakeBorder(im, top=bw, bottom=bw, left=bw, right=bw, borderType= cv2.BORDER_CONSTANT)

# Rotate -45 degrees
w, h = bordered.shape
M = cv2.getRotationMatrix2D((h/2,w/2),-45,1)
paddedrotated = cv2.warpAffine(bordered,M,(h,w))
# DEBUG cv2.imwrite('1.tif',paddedrotated)

# Sum the elements of each column and find column with most white pixels
colsum = np.sum(paddedrotated,axis=0,dtype=np.float)
col = np.argmax(colsum)
# DEBUG cv2.imwrite('2.tif',colsum)

# Fill with black except for the line we have located which we make white
paddedrotated[:,:] = 0
paddedrotated[:,col] = 255

# Rotate back to straight
w, h = paddedrotated.shape
M = cv2.getRotationMatrix2D((h/2,w/2),45,1)
straight = cv2.warpAffine(paddedrotated,M,(h,w))

# Remove padding and save to disk
straight = straight[bw:-bw,bw:-bw]
cv2.imwrite('result.png',straight)

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

col = np.argmax(colsum)

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

Вот вывод:

enter image description here


Ключевые слова : обнаружение линии, обнаружение линии, поворот, отступ, граница, проекция, проект, изображение, обработка изображения,Python, OpenCV, аффинный, Hough

0 голосов
/ 28 ноября 2018

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

Найти все контуры на изображении, используя поиск контуров

img = cv.imread('image.jpg')
img_gray = cv.cvtColor(img, cv.COLOR_BGR2GRAY)
ret, thresh = cv.threshold(img_gray, 127, 255, 0)
img2, contours, hierarchy = cv.findContours(thresh, CHAIN_APPROX_SIMPLE ,cv.RETR_EXTERNAL)

Это вернет много контуров, поэтому используйте цикл для сохранения только достаточно долгоконтуры.Поскольку размер изображения составляет 814x1041 пикселей, я предполагаю, что контур длинный, если он составляет не менее 10% ширины изображения, что составляет почти 100 (вы, очевидно, должны оптимизировать это значение)

long_contours = []
for contour in contours[i]:
    perimeter = cv2.arcLength(contour,True)
    if (perimeter > 0.1 * 1018)  # 10% of the image width
        long_contours.append(contour)

Теперь нарисуйте повернутое ограничениепрямоугольник вокруг тех длинных контуров, которые также могут быть линиями.Длинный контур считается линией, если его ширина намного длиннее его высоты, либо его соотношение сторон велико (например, 8, и вам также необходимо оптимизировать это значение)

for long_contour in long_contours:
    rect = cv2.minAreaRect(long_contour)
    aspec_ratio =  rect.width / rect.height

    if aspec_ratio > 8 : 
       box = cv2.boxPoints(rect)
       box = np.int0(box)
       cv2.drawContours(img,[box],0,(255,255,255),cv.FILLED)

Наконец, вы должны получитьчто-то вроде того.Пожалуйста, обратите внимание, код здесь только для ознакомления.

Rotated rectangle over a suspected line

0 голосов
/ 27 ноября 2018

Я сделал это в командной строке в терминале с ImageMagick , но вы можете применить точно такую ​​же технику с OpenCV .

Шаг 1

Возьмите изображение и поверните его на 45 градусов, добавив черные пиксели в качестве фона, где это необходимо:

convert 45.jpg -background black -rotate 45 result.png

enter image description here

Шаг 2

Теперь, опираясь на предыдущую команду, установите для каждого пикселя медиану поля шириной 1 пиксель и высотой 250 пикселей по центру:

convert 45.jpg -background black -rotate 45 -statistic median 1x250 result.png

enter image description here

Шаг 3

Теперь, снова опираясь на предыдущую команду, поверните ее на 45 градусов назад:

convert 45.jpg -background black -rotate 45 -statistic median 1x250 -rotate -45 result.png

enter image description here


Итак, в итоге, вся обработка выглядит так:

convert input.jpg -background black -rotate 45 -statistic median 1x250 -rotate -45 result.png

Очевидно, затем обрежьте его обратно до исходного размера и добавьтевместе с оригиналом для проверки:

convert 45.jpg -background black -rotate 45 -statistic median 5x250 -rotate -45 +repage -gravity center -crop 184x866+0+0 result.png
convert 45.jpg result.png +append result.png 

enter image description here


Вы также можете использовать mean статистика плюс пороговое значение вместо median так как яЭто быстрее, чем сортировка, чтобы найти медиану, однако это приводит к размытию:

convert 45.jpg -background black -rotate 45 -statistic mean 1x250 result.png

enter image description here

Ваше вновь добавленное изображение обрабатывается этимрезультат:

enter image description here

...