OpenCV ~ detecção de curva

Em qualquer cenário de direção, as marcações de faixa são uma parte importante para indicar o fluxo de tráfego e onde os veículos devem circular. Também é um ótimo ponto de partida para o desenvolvimento de carros autônomos! Com base em meu projeto anterior de detecção de faixa, implementei um sistema de detecção de faixa curva que funciona melhor e é mais robusto em ambientes desafiadores. O sistema de detecção de faixa é escrito em Python usando a biblioteca OpenCV.

Aqui estão as etapas de implementação:

  • correção de distorção

  • transformação de perspectiva

  • filtro Sobel

  • Detecção de pico de histograma

  • pesquisa janela deslizante

  • Ajuste de curva

  • Pista de Detecção de Cobertura

  • aplicar ao vídeo

correção de distorção

A lente da câmera distorce a luz recebida para focalizá-la no sensor da câmera. Embora sejam ótimos para capturar imagens de nossos ambientes, eles tendem a distorcer a luz de maneira ligeiramente imprecisa. Isso pode levar a medições imprecisas em aplicativos de visão computacional. No entanto, podemos facilmente corrigir essa distorção.

Podemos usar o tabuleiro de damas para calibrar a câmera e fazer a correção de distorção:

A câmera usada no vídeo de teste é usada para tirar 20 fotos do tabuleiro de damas, que são usadas para gerar o modelo de distorção. Primeiro convertemos a imagem em tons de cinza e então aplicamos a função cv2.findChessboardCorners(). Já sabemos que o tabuleiro de xadrez é um objeto 2D com apenas linhas retas, portanto podemos aplicar algumas transformações nos cantos detectados para alinhá-los corretamente. Use cv2.CalibrateCamera() para obter o coeficiente de distorção e a matriz da câmera. A câmera está calibrada!

Você pode então usar cv2.undistort() para não distorcer o restante dos dados de entrada. Abaixo você pode ver a diferença entre a imagem original e a retificada do tabuleiro de damas:

Código de implementação:

def undistort_img():
    # Prepare object points 0,0,0 ... 8,5,0
    obj_pts = np.zeros((6*9,3), np.float32)
    obj_pts[:,:2] = np.mgrid[0:9, 0:6].T.reshape(-1,2)
    # Stores all object points & img points from all images
    objpoints = []
    imgpoints = []
    # Get directory for all calibration images
    images = glob.glob('camera_cal/*.jpg')
    for indx, fname in enumerate(images):
        img = cv2.imread(fname)
        gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)
        ret, corners = cv2.findChessboardCorners(gray, (9,6), None)
        if ret == True:
            objpoints.append(obj_pts)
            imgpoints.append(corners)
    # Test undistortion on img
    img_size = (img.shape[1], img.shape[0])
    # Calibrate camera
    ret, mtx, dist, rvecs, tvecs = cv2.calibrateCamera(objpoints, imgpoints, img_size, None,None)
    dst = cv2.undistort(img, mtx, dist, None, mtx)
    # Save camera calibration for later use
    dist_pickle = {}
    dist_pickle['mtx'] = mtx
    dist_pickle['dist'] = dist
    pickle.dump( dist_pickle, open('camera_cal/cal_pickle.p', 'wb') )
def undistort(img, cal_dir='camera_cal/cal_pickle.p'):
    #cv2.imwrite('camera_cal/test_cal.jpg', dst)
    with open(cal_dir, mode='rb') as f:
        file = pickle.load(f)    mtx = file['mtx']
    dist = file['dist']
    dst = cv2.undistort(img, mtx, dist, None, mtx)
    return dst
undistort_img()
img = cv2.imread('camera_cal/calibration1.jpg')
dst = undistort(img) # Undistorted image

Esta é a correção de distorção aplicada à imagem da estrada. Você pode não perceber a diferença sutil, mas pode ter um grande impacto no processamento da imagem.

transformação de perspectiva

A detecção de faixas curvas no espaço da câmera não é trivial. E se quiséssemos uma visão panorâmica da entrada da garagem? Isso pode ser feito aplicando uma transformação de perspectiva à imagem. Aqui está o que parece: 

Você notou algo? Ao assumir que as pistas estão em uma superfície 2D plana, podemos ajustar um polinômio que representa com precisão as pistas no espaço da pista! Isso não é legal?

Você pode aplicar essas transformações a qualquer imagem usando a função cv2.getPerspectiveTransform() para obter a matriz de transformação e cv2.warpPerspective() para a imagem. Aqui está o código:

def perspective_warp(img,
                     dst_size=(1280,720),
                     src=np.float32([(0.43,0.65),(0.58,0.65),(0.1,1),(1,1)]),
                     dst=np.float32([(0,0), (1, 0), (0,1), (1,1)])):
    img_size = np.float32([(img.shape[1],img.shape[0])])
    src = src* img_size
    # For destination points, I'm arbitrarily choosing some points to be
    # a nice fit for displaying our warped result
    # again, not exact, but close enough for our purposes
    dst = dst * np.float32(dst_size)
    # Given src and dst points, calculate the perspective transform matrix
    M = cv2.getPerspectiveTransform(src, dst)
    # Warp the image using OpenCV warpPerspective()
    warped = cv2.warpPerspective(img, M, dst_size)
    return warped
filtro Sobel

Na versão anterior, filtrei as linhas da pista usando cores. Porém, nem sempre essa é a melhor opção. Se a estrada usar concreto de cor clara em vez de asfalto, a estrada passará facilmente pelo filtro de cor e a tubulação a perceberá como linhas de faixa brancas, o que não é robusto.

Em vez disso, podemos usar algo semelhante a um detector de borda, desta vez filtrando estradas. As linhas da pista geralmente têm alto contraste com a estrada, então podemos tirar proveito disso. O detector de arestas Canny usado na versão anterior 1 utiliza o operador Sobel para obter o gradiente da função imagem. A documentação do OpenCV tem uma boa explicação de como funciona. Usaremos isso para detectar áreas de alto contraste para filtrar marcações de faixa e ignorar estradas.

Ainda usaremos o espaço de cores HLS novamente, desta vez para detectar mudanças na saturação e luminosidade. O operador sobel é aplicado a ambos os canais, extraímos o gradiente em relação ao eixo x e adicionamos os pixels que passam pelo limite do gradiente a uma matriz binária que representa os pixels na imagem. Veja como fica no espaço da câmera e no espaço da pista:

Observe que as partes da imagem que estão longe da câmera não mantêm sua qualidade. Os dados de objetos mais distantes são muito borrados e ruidosos devido às limitações de resolução da câmera. Não precisamos focar na imagem inteira, então podemos usar apenas parte dela. É assim que a imagem (ROI) que usaremos se parece: 

Detecção de pico de histograma

Aplicaremos um algoritmo especial chamado algoritmo de janela deslizante para detectar nossas linhas de pista. No entanto, antes de podermos aplicá-lo, precisamos determinar um bom ponto de partida para o algoritmo. Funciona bem se começar onde há pixels de faixa, mas como detectamos onde esses pixels de faixa estão em primeiro lugar? é realmente muito fácil!

Obteremos um histograma da imagem em relação ao eixo x. Cada seção do histograma abaixo mostra quantos pixels brancos existem em cada coluna da imagem. Em seguida, pegamos os picos mais altos de cada lado da imagem, um para cada linha de pista. Aqui está a aparência do histograma, ao lado da imagem binária:

 

 

pesquisa janela deslizante

Um algoritmo de janela deslizante será usado para distinguir os limites da pista esquerda e direita para que possamos ajustar duas curvas diferentes que representam os limites da pista.

O algoritmo em si é muito simples. Começando da posição inicial, a primeira janela mede quantos pixels estão dentro da janela. Se o número de pixels atingir um determinado limite, ele move a próxima janela para a posição lateral média dos pixels detectados. Se não forem detectados pixels suficientes, a próxima janela começa na mesma posição horizontal. Isso continua até que a janela alcance a outra borda da imagem.

Os pixels que se enquadram na janela recebem um sinalizador. Na imagem abaixo, os pixels marcados em azul representam a faixa da direita e os pixels marcados em vermelho representam a esquerda:

Ajuste de curva

O resto do projeto é bastante simples. Aplicamos a regressão polinomial aos pixels vermelhos e azuis usando np.polyfit() respectivamente, e o detector está pronto! whaosoft  aiot  http://143ai.com

Veja como fica a curva:

Desenhar faixas de detecção

Esta é a última parte do sistema de detecção, a interface do usuário! Simplesmente criamos uma sobreposição para preencher a parte detectada da faixa, que podemos finalmente aplicar ao vídeo. Uma vez aplicado à detecção de vídeo, você deve ver a seguinte saída:

para concluir

É isso, um detector básico de faixas curvas! É muito melhor do que a versão anterior, pode até lidar com calçadas curvas! No entanto, ainda sofre um pouco com sombras e mudanças drásticas nas texturas da estrada. Em meu próximo projeto de detecção de faixa, usaremos algumas técnicas de aprendizado de máquina para desenvolver um sistema de detecção de faixa e veículo muito robusto, obrigado!

Código completo:  https://github.com/kemfic/Curved-Lane-Lines/blob/master/P4.ipynb

Link de referência:  https://www.hackster.io/kemfic/curved-lane-detection-34f771

Acho que você gosta

Origin blog.csdn.net/qq_29788741/article/details/131354881
Recomendado
Clasificación