Phân đoạn các đường dày chồng chéo trên một hình ảnh nhị phân
Tôi có một hình ảnh nhị phân như được hiển thị bên dưới sau khi áp dụng các đường dẫn tiền xử lý và phát hiện khác nhau lên hình ảnh gốc.

Như trong hình thực tế có 2 đường băng (đường băng) dành cho các máy bay đang cắt nhau trên một vùng giao nhau. Những gì tôi cần là tách cả hai đường băng và trả lại đường viền của chúng. Tôi đã kiểm tra các hàm opencv liên quan đến các tính năng đường viền nhưng không gặp may. cv2.fitLine
có vẻ ổn nhưng nó chỉ hoạt động nếu chỉ có một đường duy nhất trong đường viền. Hình ảnh kết quả khi các mặt nạ được áp dụng sẽ trông như thế này:

Trả lời
Đây là một cách tiếp cận khả thi, vừa được thực hiện trong Terminal với ImageMagick , nhưng bạn sẽ có thể làm khá nhiều điều tương tự trong Python với Wand hoặc với scikit-image và medial_axis .
Đầu tiên, tạo khung cho hình ảnh:
magick runways.png -threshold 50% -morphology Thinning:-1 Skeleton skeleton.png

Sau đó, chạy "Hough Line Detection" để tìm các đường dài hơn 130 pixel và yêu cầu kết quả ở dạng bảng:
magick skeleton.png -hough-lines 9x9+130 mvg:-
Đầu ra
# 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
Điều đó có nghĩa là nó đã phát hiện ra 2 dòng:
- một đường từ tọa độ 297,0 đến tọa độ 286,589, với chiều dài = 255 pixel ở 1 độ so với phương thẳng đứng
- một đường từ tọa độ 0,591 đến tọa độ 464,333, với chiều dài = 189 pixel ở 61 độ theo chiều dọc
Để minh họa, tôi sẽ vẽ hình đầu tiên màu đỏ và hình vẽ thứ hai màu xanh lá cây:
magick runways.png \
-fill red -draw "line 297,0 286,589" \
-fill lime -draw "line 0,591 464,333" result.png

Từ khóa : Python, xử lý ảnh, bộ xương, bộ xương, làm mỏng, đường băng, đường băng, giao lộ, Phát hiện đường Hough.
Tôi đã cố gắng giải quyết vấn đề của bạn với C ++ tham chiếu câu trả lời cũ của tôi .
một số bước:
--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);

tạo hai bản sao của hình ảnh nhị phân và vẽ các đường bằng cách sử dụng các điểm khuyết tật
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);


tìm đường viền từ hình ảnh và vẽ chúng (tôi đã tìm thấy chỉ số đường viền được mã hóa cứng, cần được cải thiện)
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;
}