Слияние HoughLines

Я застрял в одном месте в моем коде. Во-первых, краткое пояснение того, что я делаю: в качестве входных данных используется изображение пола. С помощью алгоритма Canny и HoughLinesP я хочу разделить всю стену на множество «маленьких» частей, как вы можете видеть здесь, что в то же время идеальный выход (здесь без консервов) хотелось бы получить — отрезок между двумя красными линиями.

введите описание изображения здесь

Хорошо, так как я получаю на самом деле это здесь

введите описание изображения здесь

Интересно, как объединить линии, которые слишком близки друг к другу. Например, строки 2,4,3,5,6 должны быть одной строкой и также считаться одной. Строка с 7 по 15 должна быть также одна, которая будет второй строкой.

Конечно, я провел небольшое исследование и попробовал это:

#include <opencv/cv.h>
#include <opencv/highgui.h>
#include <opencv2/opencv.hpp>
#include <opencv2/core/core.hpp>
#include <experimental/filesystem>

using namespace cv;
using namespace std;

Mat srcReal = //here's this image http://imgur.com/a/Kcjp6
Mat src, dst, cdst;
vector<Vec4i> lines;

void wallMapping(Mat src) {

Scalar mu, sigma;
meanStdDev(src, mu, sigma);

Canny(src, dst, mu.val[0] - sigma.val[0], mu.val[0] + sigma.val[0], 3, false);

cvtColor(dst, cdst, CV_GRAY2BGR);
HoughLinesP(dst, lines, 1, CV_PI / 2, 50, 50, 200);

sort(lines.begin(), lines.end(), vec4iSortByX());                                 ///sort all lines by number

for (size_t i = 1; i < lines.size(); i++) {
Vec4i current = lines[i];                                                   ///set current lines
Point pt1 = Point(current[0], current[1]);
Point pt2 = Point(current[2], current[3]);

Vec4i previous = lines[i - 1];                                              ///set previous lines
Point ppt1 = Point(previous[0], previous[1]);
Point ppt2 = Point(previous[2], previous[3]);

int gradient1, gradient2;
if (pt1.x - pt2.x != 0) {
gradient1 = (pt1.y - pt2.y) / (pt1.x - pt2.x);
gradient2 = (ppt1.y - ppt2.y) / (ppt1.x - ppt2.x);
}
Point avrgpt1, avrgpt2;

if (gradient1 == gradient2) {

avrgpt1.x = (pt1.x + ppt1.x) / 2;
avrgpt2.x = (pt2.x + ppt2.x) / 2;

avrgpt1.y = (pt1.y + ppt1.y) / 2;
avrgpt2.y = (pt2.y + ppt2.y) / 2;
}

double angle = atan2(ppt2.y - ppt1.y, ppt2.x - ppt1.x) * 180.0 / CV_PI;     ///draw only vertical lines (90 degree)
if (angle) {
std::vector<int> lineLabel;
int numLines = cv::partition(lines, lineLabel, isEqual);
line(cdst, avrgpt1, avrgpt2, Scalar(0, 0, 255), 2, CV_AA);
}

cv::putText(cdst, to_string(i+1), pt2 + Point(0, 10), 4, 1, Scalar(0, 255, 0), 1, 8, false);

//some other stuff
}

//main
int main(int argc, char *argv[]) {
wallMapping(srcReal);

waitKey(0);
return 0;
}

Но если вы посмотрите на рисунок выше, вы увидите, что моя идея слияния в коде не работает. Так что я был бы рад идее, подходам или исправлениям моего кода! Спасибо!

2

Решение

Нарисуйте линии в отдельном бинарном изображении, выполнив морфологическое замыкание на них так, чтобы те, которые находятся близко друг к другу, слились, а затем размыли изображение небольшим ядром, например, 3х3, чтобы оставить тонкие линии.

После этого получите ненулевые координаты из только что созданного двоичного изображения и нарисуйте эти координаты в желаемом изображении.

Чтобы вернуть эти новые линии обратно в вектор, вы можете найти контуры внутри двоичного изображения с помощью findContours() а затем просто найдите 2 крайние точки (точки экстремальных значений x или y) каждого контура — это точки, описывающие линию.

0

Другие решения

Других решений пока нет …

По вопросам рекламы [email protected]