Segmentando linhas grossas sobrepostas em uma imagem binária

Aug 16 2020

Eu tenho uma imagem binária conforme mostrado abaixo depois de aplicar vários pipelines de pré-processamento e detecção na imagem original.

Como pode ser visto na imagem, existem na verdade 2 pistas (pistas) para aviões que se cruzam em uma região de interseção. O que preciso é dividir as duas pistas e retornar seus contornos. Eu verifiquei as funções do opencv em relação às características de contorno, mas não tive sorte. cv2.fitLineparece ok, mas só funciona se houver apenas uma linha no contorno. A imagem resultante quando as máscaras são aplicadas deve ter a seguinte aparência:

Respostas

3 MarkSetchell Aug 30 2020 at 23:17

Aqui está uma abordagem possível, feita apenas no Terminal com ImageMagick , mas você deve ser capaz de fazer praticamente o mesmo em Python com Wand ou com scikit-image e o medial_axis .

Primeiro, esqueletize a imagem:

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

Em seguida, execute uma "Detecção de linha Hough" procurando linhas com mais de 130 pixels e peça os resultados em uma forma tabular:

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

Resultado

# 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

Isso significa que detectou 2 linhas:

  • uma linha das coordenadas 297,0 às coordenadas 286,589, com um comprimento = 255 pixels a 1 grau na vertical
  • uma linha das coordenadas 0,591 às coordenadas 464,333, com um comprimento = 189 pixels a 61 graus na vertical

Só para ilustrar, vou desenhar o primeiro em vermelho e o segundo em verde:

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

Palavras - chave : Python, processamento de imagem, esqueleto, esqueleto, desbaste, pista, pistas, interseção, Detecção de linha de Hough.

2 sturkmen Aug 30 2020 at 21:19

Tentei resolver seu problema com C ++ referenciando minha resposta anterior .

alguns passos:

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

crie duas cópias da imagem binária e desenhe linhas usando pontos de defeito

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

encontre contornos de imagens e desenhe-os (i índice de contorno encontrado codificado, precisa ser melhorado)

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