Я применил функцию обнаружения краев Canny к исходному изображению, а затем использовал функцию findContours, чтобы найти самый длинный контур. Но после этого я хотел бы использовать алгоритм подгонки линий (функция подгонки) в OpenCV, чтобы нарисовать линию вдоль линии небо-море на исходном изображении.
Исходное изображение:
После обнаружения края Кэнни и определения самого длинного контура:
Результат, ожидаемый после подгонки линии:
Любая помощь будет высоко ценится.
Вы не просто используете детектор края Canny для горизонта.
(1) Примените медианный фильтр достаточно большой, чтобы скрыть мелкие объекты.
cv::medianBlur( imgOriginal, blurred, 101 );
(2) Рассчитайте величину градиента. Например. используя некрасивую прямую разницу следующим образом:
cv::Mat m;
blurred.convertTo(m,CV_32F);
cv::Mat crop = m( cv::Rect(0,0,m.cols-1,m.rows-1) );
const cv::Mat shiftx = m( cv::Rect(1,0,m.cols-1,m.rows-1) );
const cv::Mat shifty = m( cv::Rect(0,1,m.cols-1,m.rows-1) );
cv::Mat dx,dy;
cv::subtract( shiftx, crop, dx );
cv::subtract( shifty, crop, dy );
cv::pow( dx, 2.0, dx );
cv::pow( dy, 2.0, dy );
cv::add( dx, dy, dx );
m.setTo(0);
cv::sqrt( dx, crop );
(3) Соберите точки, где величина градиента больше, скажем, наполовину максимальной.
cv::minMaxLoc( m, &mi, &ma );
const float thr = ma/2.0;
std::vector< cv::Point2f > pts;
for ( int y=0; y<m.rows;++y)
// ...
(4) И наложи на них линию.
Вы должны получить хорошую форму.
Других решений пока нет …