Fesor
@Fesor
Full-stack developer (Symfony, Angular)

Поиск повернутых объектов?

Собственно есть изображение (уже обработанное, применен фильтр Canny). На нем изображены контуры какой-то фигуры. Фигура всегда должна стоять вертикально (для последующей обработки). Контур всей фигуры вписывается в прямоугольник. На данный момент проблема решена следующим образом. Находятся крайние вертикальные/горизонтальные точки, строятся линии. Выбирается максимальная по длине линия, высчитывается угл между перпендикуляром. Происходит вращение изображения. Результат правильный лишь в 50% случаев, так как изза поворота объекта эти «вершины» находятся с довольно большой погрешностью.


Объекты представляю собой контуры грушевидной формы.


Как вариант — попробовать методом подбора, повернуть на определенный угл, посмотреть размеры прямоугльника (высоту) в который вписывается контур, если этот размер больше — поворачивать еще до того момента пока высота не станет варьироваться в пределах одного пикселя. Угл обычно не большой, до 15 градусов, но по сути такой способ выходит довольно прожорливым. Есть ли какие-либо алгоритмы для подобных задач?


В конечном этоге я должен получить координаты точек прямоугольника и угл поворота.


Пример изображения:
5adb4da51343a807b3eb10c875aa782a.png
  • Вопрос задан
  • 3617 просмотров
Пригласить эксперта
Ответы на вопрос 6
@kmike
Как-то так делал (через питоний биндинг к OpenCV):

def how_to_make_horizontal(contour):
    """ Returns rotate center and angle that would make contour horizontal """
    rect = cv.BoundingRect(contour)
    box = cv.MinAreaRect2(contour)

    x, y, w, h = rect
    p1, p2, angle = box
    if angle > 45:
        angle -= 90
    if angle < -45:
        angle += 90
    rotate_center = x+w/2, y+h/2
    return angle, rotate_center


Но у меня в задаче из растра предварительно контур удавалось получить, обработав изображение через cv.MorphologyEx с кастомным ядром (чтоб избавиться от дефектов — закрыть разрывы и тд) и натравив cv.FindContours. Вроде можно просто взять все точки и передать их в cv.MinAreaRect, не знаю. См.

opencv.willowgarage.com/documentation/cpp/imgproc_structural_analysis_and_shape_descriptors.html#cv-minarearect
Ответ написан
Комментировать
VasG
@VasG
А можно хотя бы один пример объектов? Лучше один раз увидеть.
Ответ написан
Mrrl
@Mrrl
Заводчик кардиганов
Я бы искал ось симметрии. Но пока не очень представляю, как именно. Например, брать все пары точек, строить для них серединный перпендикуляр, и считать статистику их параметров в пространстве прямых (угол, расстояние от центра). Не исключено, что максимум даст правильное направление.
Ответ написан
Mrrl
@Mrrl
Заводчик кардиганов
Нет, там берется центр масс (xc,yc), потом считаются коэффициенты a11=sum(xi-xc)^2, a12=a21=sum((xi-xc)*(yi-yc)), a22=sum((yi-yc)^2), где (xi,yi) — координаты всех точек. Дальше у матрицы ((a11 a12) (a21 a22)) надо взять собственные векторы — они и дадут ориентацию объекта. Или не дадут… Отделить бы как-нибудь внутренние точки от внешних… Надо много экспериментировать, задача непростая и очень эвристическая.
Ответ написан
@vedmaka
лампочка!
Ответ написан
Комментировать
lsdima
@lsdima
Я бы попробовал так: Взяв граничную область (где присутствуют разные по цвету пиксели) можно найти направление градиента/заливки. Иллюстрация, чтобы было понятней: habrastorage.org/storage2/e77/b42/392/e77b42392bce4c4b73b70e4ec8c4057f.png
Вооружившись этим знанием можно проанализировать все граничные области, а суммой найденных направлений и будет (теоретически) искомый угол поворота. В вашем случае для этого будет достатчно одного прохода пиксельного шейдера. Однако следует учесть что из-за двоичного формата фаших образцов будут значительные погрешности.
Ответ написан
Комментировать
Ваш ответ на вопрос

Войдите, чтобы написать ответ

Войти через центр авторизации
Похожие вопросы