Установите плавную кривую в двоичном изображении - PullRequest
0 голосов
/ 03 июня 2019

Я хочу разместить плавную линию в двоичном изображении.

Это изображение является результатом предварительной обработки с использованием контраста, контура, скелета, ближайшего соседа, разделения контура,и т. д. Исходное изображение

Я думал, что подгонка кривой будет очень простой, как только я получу массив (x, y) белых точек.Но когда я пытаюсь вписать кривую в это изображение, появляется зигзагообразная линия из-за нескольких значений в определенном x.Мне нужно обобщенное решение моей проблемы.Мое изображение может отличаться (я делаю приложение).Может иметь 4-5 значений для определенного х или наоборот.

Методы, которые я пробовал:

  1. Выпуклое изображение с выпуклым корпусом (изображение не гладкое)

Ближайшее соседнее соединение.(изображение не является плавным)

соскобы интерполировать (зигзагообразная линия появляется из-за нескольких y @x)

сплайн-кривая matplotlib

Подскажите, как разместить плавную кривую на таких изображениях.

Ответы [ 3 ]

0 голосов
/ 03 июня 2019

Это может быть полезно, я не могу сказать наверняка, потому что я не знаю характеристик всех ваших целевых изображений.

  1. Преобразование изображения в оттенки серого
  2. Примените эрозию к своему изображению для некоторого количества шагов на основе заданных вами критериев остановки (на основе некоторых метрик, таких как подключенные компоненты, может быть)

Проверьте библиотеку OpenCV на наличие соответствующих вызовов API в разделе морфологического преобразования.

Вот пример применения эрозии к вашему изображению за несколько шагов.

enter image description here

0 голосов
/ 01 июля 2019

Эту проблему можно решить, используя следующие шаги, и приведенный ниже код:

  1. Сначала подключите все ближайшие точки соседей. Это обеспечит массив в пути, по которому идет кривая или график.

  2. Затем используйте сглаживание univariateSpline, чтобы сгладить кривую.

Проблема решена - зигзагообразная линия станет гладкой в ​​соответствии с кривой.

Код для подключения всех ближайших соседей:

def distance(P1, P2):
    return ((P1[0] - P2[0])**2 + (P1[1] - P2[1])**2) ** 0.5

def optimized_path(coords, start=None):
    if start is None:
        start = coords[0]
    pass_by = coords
    path_connected = [start]
    pass_by.remove(start)
    while pass_by:
        nearest = min(pass_by, key=lambda x: distance(path_connected[-1], x))
        path_connected.append(nearest)
        pass_by.remove(nearest)
    return path_connected

start = None
    points=[[i,j] for i,j in zip(x_data,y_data)]
    points = optimized_path(points,start)

Код для сглаживания ближайших соседних точек:

# Smoothing
distance_smooth = np.cumsum( np.sqrt(np.sum( np.diff(points, axis=0)**2, axis=1 )) )
distance_smooth = np.insert(distance_smooth, 0, 0)/distance_smooth[-1]
splines = [UnivariateSpline(distance_smooth, coords, k=5, s=None) for coords in points.T]
alpha = np.linspace(0, 1, 75)
points_fitted = np.vstack( spl(alpha) for spl in splines ).T

Это окончательное изображение - Гладкое изображение

0 голосов
/ 03 июня 2019

Я понимаю, что вопрос означает, что вы хотите найти кривую по данным в виде списка координат x и y.

Выберите точку, чтобы начать, например, там, где высокая плотностьуказывает вдоль стороны или края графика.

Найдите медиану в одну или другую сторону, исключите листовки и найдите среднее значение.Переместитесь и сделайте это снова.

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

Медиана позволит избежать перевеса для удаленных точек и будет стремиться сильно тянуться к центру данных в этой точке в x (или y, если хотите).

Среднее часто имеет более сильную связь сфизическая теория или модель, которую вы можете исследовать.

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

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

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...