Segmentar líneas gruesas superpuestas en una imagen binaria

Aug 16 2020

Tengo una imagen binaria como se muestra a continuación después de aplicar varias tuberías de preprocesamiento y detección en la imagen original.

Como se ve en la imagen, en realidad hay 2 pistas (asfaltos) para aviones que se cruzan entre sí en una región de intersección. Lo que necesito es dividir ambas pistas y devolver sus contornos. Revisé las funciones de opencv con respecto a las características del contorno, pero no tuve suerte. cv2.fitLineparece estar bien, pero solo funciona si solo hay una línea en el contorno. La imagen resultante cuando se aplican las máscaras debería verse así:

Respuestas

3 MarkSetchell Aug 30 2020 at 23:17

Aquí hay un enfoque posible, recién hecho en Terminal con ImageMagick , pero debería poder hacer más o menos lo mismo en Python con Wand o con scikit-image y medial_axis .

Primero, esqueletice la imagen:

magick runways.png -threshold 50% -morphology Thinning:-1 Skeleton skeleton.png

Luego, ejecute una "Detección de línea Hough" buscando líneas de más de 130 píxeles y solicite los resultados en forma de tabla:

magick skeleton.png -hough-lines 9x9+130 mvg:-

Salida

# Hough line transform: 9x9+130
viewbox 0 0 464 589
# x1,y1 x2,y2 # count angle distance
line 297.15,0 286.869,589  # 255 1 476
line 0,591.173 464,333.973  # 189 61 563

Eso significa que ha detectado 2 líneas:

  • una línea desde las coordenadas 297,0 hasta las coordenadas 286,589, con una longitud = 255 píxeles a 1 grado de la vertical
  • una línea desde las coordenadas 0,591 hasta las coordenadas 464,333, con una longitud = 189 píxeles a 61 grados de la vertical

Solo para ilustrar, dibujaré el primero en rojo y el segundo en verde:

magick runways.png                       \
   -fill red  -draw "line 297,0 286,589" \
   -fill lime -draw "line 0,591 464,333" result.png

Palabras clave : Python, procesamiento de imágenes, esqueleto, esqueletizado, adelgazamiento, pista, pistas, intersección, Hough Line Detection.

2 sturkmen Aug 30 2020 at 21:19

Intenté resolver su problema con C ++ haciendo referencia a mi respuesta anterior .

Algunos pasos:

--after finding contours find defect points by convexityDefects

approxPolyDP(contours[i], contours[i], 9, true);
convexHull(contours[i], contoursHull, true);
convexityDefects(contours[i], contoursHull, defects);

crear dos copias de la imagen binaria y dibujar líneas usando puntos de defecto

Vec4i defpoint0 = defects[0];
Vec4i defpoint1 = defects[1];
Vec4i defpoint2 = defects[2];
Vec4i defpoint3 = defects[3];
line(bw0, contours[i][defpoint0[2]], contours[i][defpoint1[2]], Scalar(0), 2);
line(bw0, contours[i][defpoint2[2]], contours[i][defpoint3[2]], Scalar(0), 2);

line(bw1, contours[i][defpoint0[2]], contours[i][defpoint3[2]], Scalar(0), 2);
line(bw1, contours[i][defpoint1[2]], contours[i][defpoint2[2]], Scalar(0), 2);

encontrar contornos a partir de imágenes y dibujarlos (he codificado el índice de contornos encontrado, es necesario mejorarlo)

findContours(bw0, contours, RETR_EXTERNAL, CHAIN_APPROX_NONE);
drawContours(src, contours, 1, Scalar((rand() & 255), (rand() & 255), (rand() & 255)), 2);

findContours(bw1, contours, RETR_EXTERNAL, CHAIN_APPROX_NONE);
drawContours(src, contours, 2, Scalar((rand() & 255), (rand() & 255), (rand() & 255)), 2);

#include <opencv2/highgui.hpp>
#include <opencv2/imgproc.hpp>
#include <iostream>

using namespace cv;
using namespace std;

int main(int argc, char** argv)
{
    Mat src = imread("e:/test/crossing_lines.png");
    if (src.empty())
        return -1;

    Mat bw,bw0,bw1;
    cvtColor(src, bw, COLOR_BGR2GRAY);
    bw = bw > 127;
    bw0 = bw.clone();
    bw1 = bw.clone();
    // Find contours
    vector<vector<Point> > contours;
    vector<int> contoursHull;
    vector<Vec4i> defects;
    findContours(bw, contours, RETR_EXTERNAL, CHAIN_APPROX_NONE);

    for (size_t i = 0; i < contours.size(); i++)
    {
        if (contourArea(contours[i]) > 500)
        {
            approxPolyDP(contours[i], contours[i], 9, true);
            convexHull(contours[i], contoursHull, true);
            convexityDefects(contours[i], contoursHull, defects);
 
            Vec4i defpoint0 = defects[0];
            Vec4i defpoint1 = defects[1];
            Vec4i defpoint2 = defects[2];
            Vec4i defpoint3 = defects[3];
            line(bw0, contours[i][defpoint0[2]], contours[i][defpoint1[2]], Scalar(0), 2);
            line(bw0, contours[i][defpoint2[2]], contours[i][defpoint3[2]], Scalar(0), 2);

            line(bw1, contours[i][defpoint0[2]], contours[i][defpoint3[2]], Scalar(0), 2);
            line(bw1, contours[i][defpoint1[2]], contours[i][defpoint2[2]], Scalar(0), 2);
        }
    }
    findContours(bw0, contours, RETR_EXTERNAL, CHAIN_APPROX_NONE);
    drawContours(src, contours, 1, Scalar((rand() & 255), (rand() & 255), (rand() & 255)), 2);

    findContours(bw1, contours, RETR_EXTERNAL, CHAIN_APPROX_NONE);
    drawContours(src, contours, 2, Scalar((rand() & 255), (rand() & 255), (rand() & 255)), 2);
    imshow("src", src);
    imshow("bw0", bw0);
    imshow("bw1", bw1);
    waitKey();
    return 0;
}