Segmentation de lignes épaisses superposées sur une image binaire

Aug 16 2020

J'ai une image binaire comme indiqué ci-dessous après avoir appliqué divers pipelines de prétraitement et de détection sur l'image d'origine.

Comme on le voit sur la photo, il y a en fait 2 pistes (tarmacs) pour les avions qui se croisent sur une zone d'intersection. Ce dont j'ai besoin, c'est de diviser les deux pistes et de rendre leurs contours. J'ai vérifié les fonctions d'opencv concernant les caractéristiques de contour mais je n'ai pas eu de chance. cv2.fitLinesemble correct mais cela ne fonctionne que s'il n'y a qu'une seule ligne dans le contour. L'image résultante lorsque les masques sont appliqués doit ressembler à ceci:

Réponses

3 MarkSetchell Aug 30 2020 at 23:17

Voici une approche possible, juste faite dans Terminal avec ImageMagick , mais vous devriez pouvoir faire à peu près la même chose en Python avec Wand ou avec scikit-image et medial_axis .

Tout d'abord, squelettisez l'image:

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

Ensuite, lancez une "Détection de ligne Hough" à la recherche de lignes de plus de 130 pixels et demandez les résultats sous forme de tableau:

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

Production

# 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

Cela signifie qu'il a détecté 2 lignes:

  • une ligne allant des coordonnées 297,0 aux coordonnées 286 589, avec une longueur = 255 pixels à 1 degré par rapport à la verticale
  • une ligne allant des coordonnées 0,591 aux coordonnées 464333, d'une longueur = 189 pixels à 61 degrés par rapport à la verticale

Juste pour illustrer, je vais dessiner le premier en rouge et le second en vert:

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

Mots clés : Python, traitement d'image, squelette, squelette, éclaircie, piste, pistes, intersection, détection de ligne Hough.

2 sturkmen Aug 30 2020 at 21:19

J'ai essayé de résoudre votre problème avec C ++ en référençant mon ancienne réponse .

quelques étapes:

--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);

créer deux copies d'une image binaire et dessiner des lignes en utilisant des points de défaut

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);

trouver des contours à partir d'images et les dessiner (i index de contour trouvé codé en dur, doit être amélioré)

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;
}