Как найти пересечение линий с opencv

#python #opencv #line-intersection #straight-line-detection

Вопрос:

На этом рисунке я пытаюсь найти точки пересечения между длинными белыми линиями между гоночными полосами и короткими перпендикулярными

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

Вот мой код:

 import numpy as np
import matplotlib.pyplot as plt
from matplotlib.widgets import Slider, Button

import cv2

image = cv2.imread('80_frame140.png')


def get_white_2(img, low_threshold, high_threshold):
    
    gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)

    kernel_size = 5
    blur = cv2.GaussianBlur(gray, (kernel_size, kernel_size),0)
    
    edges = cv2.Canny(blur, low_threshold, high_threshold)
    
    return edges

def get_lines(edges, min_length, max_gap):

    rho = 1  # distance resolution in pixels of the Hough grid
    theta =  0.5* np.pi / 180  # 0.5 angular resolution in radians of the Hough grid
    threshold = 10#15 # minimum number of votes (intersections in Hough grid cell)
    min_line_length = min_length  # minimum number of pixels making up a line
    max_line_gap = max_gap # maximum gap in pixels between connectable line segments
    
    # Run Hough on edge detected image
    # Output "lines" is an array containing endpoints of detected line segments
    lines = cv2.HoughLinesP(edges, rho, theta, threshold, np.array([]),
                        min_line_length, max_line_gap)
    
    line_img = edges.copy() * 0
    for line in lines:
        for x1,y1,x2,y2 in line:
            cv2.line(line_img,(x1,y1),(x2,y2),(255),2)

    return line_img

def update_1(val):
    imgplot.set_data(get_white_2(image, int(low_slider.val), int(high_slider.val)))
    fig.canvas.draw_idle()
    
def line_button(event):
    plt.close('all')
    
def update_2(val):
    imgplot.set_data(get_lines(where_white, int(min_length_slider.val), int(max_gap_slider.val)))
    fig.canvas.draw_idle()

def main():
    # Define initial parameter
    init_low = 145
    init_high = 150
    
    
    # Create the figure and the line that we will manipulate
    fig, ax = plt.subplots()
    imgplot = plt.imshow(get_white_2(image, init_low, init_high), cmap='gray')
    #ax.set_xlabel('Time [s]')
    
    axcolor = 'lightgoldenrodyellow'
    ax.margins(x=0)
    
    # adjust the main plot to make room for the sliders
    plt.subplots_adjust(left=0.25, bottom=0.25)
    
    # Make a horizontal slider to control low_threshold.
    ax_low= plt.axes([0.25, 0.1, 0.65, 0.03], facecolor=axcolor)
    low_slider = Slider(
        ax=ax_low,
        label='low_threshold',
        valmin=0,
        valmax=150,
        valinit=init_low,
    )
    
    # Make a vertically oriented slider to control high_threshold
    ax_high = plt.axes([0.1, 0.25, 0.0225, 0.63], facecolor=axcolor)
    high_slider = Slider(
        ax=ax_high,
        label='high_threshold',
        valmin=100,
        valmax=255,
        valinit=init_high,
        orientation="vertical"
    )
    # The function to be called anytime a slider's value changes
    
    # register the update function with each slider
    low_slider.on_changed(update_1)
    high_slider.on_changed(update_1)
    
    # Create a `matplotlib.widgets.Button` to go to k selection.
    lineax = plt.axes([0.8, 0.025, 0.1, 0.04])
    button = Button(lineax, 'Lines', color=axcolor, hovercolor='0.975')
    
    
    button.on_clicked(line_button)
    where_white = get_white_2(image,int(low_slider.val), int(high_slider.val))
    
    plt.show()
    
    init_min_length = 50
    init_max_gap = 20
    # Create the figure and the line that we will manipulate
    fig, ax = plt.subplots()
    imgplot = plt.imshow(get_lines(where_white, init_min_length, init_max_gap), cmap='gray')
    
    axcolor = 'lightgoldenrodyellow'
    ax.margins(x=0)
    
    # adjust the main plot to make room for the sliders
    plt.subplots_adjust(left=0.25, bottom=0.25)
    
    # Make a horizontal slider to control min_line_length.
    ax_min_length = plt.axes([0.25, 0.1, 0.65, 0.03], facecolor=axcolor)
    min_length_slider = Slider(
        ax=ax_min_length,
        label='min_length',
        valmin=5,
        valmax=100,
        valinit=init_min_length,
    )
    
    # Make a vertically oriented slider to control the max_gap
    ax_max_gap = plt.axes([0.1, 0.25, 0.0225, 0.63], facecolor=axcolor)
    max_gap_slider = Slider(
        ax=ax_max_gap,
        label='max_gap',
        valmin=0,
        valmax=30,
        valinit=init_max_gap,
        orientation="vertical"
    )
    
    min_length_slider.on_changed(update_2)
    max_gap_slider.on_changed(update_2)
    
    plt.show()
    
if __name__ =='__main__':
    main()
 

С помощью первого изображения я могу получить обнаружение белых деталей:

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

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

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

Но я не могу найти соответствующие настройки для обнаружения перпендикулярных линий

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

Может ли кто-нибудь предложить соответствующие настройки или лучший метод

Комментарии:

1. вы можете найти пересечение линий с помощью cv2 с помощью contours метода, прочитайте документы и попробуйте…

2. «контуры» — это не метод, это вещь. поиск контуров не поможет, потому что (1) они замкнуты, поэтому для любой линии вы получите тонкий контур в форме прямоугольника (2), который все еще не учитывает пересечения

3. @fenaux пожалуйста, опишите цель, а не выбранный вами подход («поиск пересечений»). зачем ты это делаешь? зачем?

4. это перспективная трансформация, быстрая и грязная в фоторедакторе. результаты могут быть улучшены. это то, что вы можете надеяться извлечь из картины. imgur.com/a/VHMesYo

5. Если я правильно понимаю, параллельные линии, где находятся бегуны, легко найти. Вы пытаетесь найти линии в правом верхнем углу изображения? Может быть, улучшить их? Расширение должно немного усилить белые линии.