Хобрук: Ваш путь к мастерству в программировании

Преобразование открытой кривой в список упорядоченных пикселей: тестовый код Python с numpy

У меня есть изображение открытой кривой в массиве numpy, и мне нужно построить список координат точек, упорядоченных в соответствии с их положением на кривой. Я написал черновик скрипта, используя numpy и махоты. Это может быть не оптимально.

Я знаю, что OpenCV может сделать это для замкнутой кривой. Может ли OpenCV сделать то же самое (быстрее) с открытой кривой?

Например, если исходная кривая:

[[0 0 0 0 0 0 0]
 [0 1 0 0 1 0 0]
 [0 0 1 0 0 1 0]
 [0 0 0 1 1 0 0]
 [0 0 0 0 0 0 0]]

Используя np.where(myarray==1), я могу получить индексы пикселей:

(array([1, 1, 2, 2, 3, 3]), array([1, 4, 2, 5, 3, 4]))

Но это не то, что мне нужно. Мой скрипт выдает индексы с учетом порядка пикселей на кривой:

i= 0 ( 1 , 1 )
i= 1 ( 2 , 2 )
i= 2 ( 3 , 3 )
i= 3 ( 3 , 4 )
i= 4 ( 2 , 5 )
i= 5 ( 1 , 4 )

Я хотел бы оптимизировать свой сценарий. Любые идеи?

08.06.2011

  • Я написал другую версию: ссылка 17.06.2011
  • Дорогие друзья, я написал расширение для работы с замкнутой кривой: [ссылка]dip4fish.blogspot.com/2011/06/ 20.06.2011

Ответы:


1

Предполагая, что в матрице/изображении присутствует только одна кривая и что каждая точка на кривой имеет от 1 до 2 соседей, следующая функция предоставит необходимые вам результаты.

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

import numpy as np

def find_chain(mat):
  locs=np.column_stack(np.nonzero(mat))
  chain=[np.array([0,0])]
  while locs.shape[0]>0:
    dists=((locs-np.vstack([chain[-1]]*locs.shape[0]))**2).sum(axis=1)
    next=dists.argmin()
    if dists.min()<=2 or len(chain)==1:
      chain.append(locs[next,:])
      locs=locs[np.arange(locs.shape[0])!=next,:]
    else:
      chain=[chain[0]]+chain[1::][::-1]
  return np.vstack(chain[1::]),((chain[1]-chain[-1])**2).sum()<=2

Для открытой кривой:

>>> mat1=np.array([[0, 0, 0, 0, 0, 0, 0],
...                [0, 1, 0, 0, 1, 0, 0],
...                [0, 0, 1, 0, 0, 1, 0],
...                [0, 0, 0, 1, 1, 0, 0],
...                [0, 0, 0, 0, 0, 0, 0]])
>>> points,isclosed=find_chain(mat1)
>>> points
array([[1, 1],
       [2, 2],
       [3, 3],
       [3, 4],
       [2, 5],
       [1, 4]])
>>> isclosed
False

И для замкнутой кривой:

>>> mat2=np.array([[0, 0, 0, 0, 0],
...                [0, 0, 1, 0, 0],
...                [0, 1, 0, 1, 0],
...                [0, 1, 0, 1, 0],
...                [0, 0, 1, 0, 0],
...                [0, 0, 0, 0, 0]])
>>> points,isclosed=find_chain(mat2)
>>> points
array([[1, 2],
       [2, 1],
       [3, 1],
       [4, 2],
       [3, 3],
       [2, 3]])
>>> isclosed
True

И кривая, где начальная точка (ближайшая точка к началу координат) делит кривую на две части.

>>> mat3=np.array([[0, 0, 0, 0, 0],
...                [0, 1, 1, 1, 0],
...                [0, 1, 0, 0, 0],
...                [0, 1, 0, 0, 0],
...                [0, 0, 0, 0, 0],
...                [0, 0, 0, 0, 0]])
>>> points,isclosed=find_chain(mat3)
>>> points
array([[1, 3],
       [1, 2],
       [1, 1],
       [2, 1],
       [3, 1]])
>>> isclosed
False
23.06.2011
  • Спасибо. Ваш код действительно компактнее моего. Зависимость только от numpy также является преимуществом. Для обработки кривой, полученной морфологическим прореживанием, необходима некоторая предварительная обработка, поскольку у пикселя может быть три соседа. 26.06.2011
  • Новые материалы

    Как сделать все элементы равными из списка в минимальных операциях в Python, используя math.ceil()
    Сегодня мы узнаем, как найти минимальные операции, необходимые для того, чтобы сделать все элементы из списка равными, используя Python в качестве языка программирования. Я использую PyCharm в..

    Создание пользовательских событий в React Native
    Обновление: это решение больше не работает, поскольку React Native не включает стандартную библиотеку Node. Однако есть автономные модули, в которых реализован API EventEmitter. Рассмотрите..

    За кулисами метода JavaScript Array.filter()
    Array.filter() — это встроенный в JavaScript метод, который создает новый массив со всеми элементами исходного массива, прошедшими определенный тест. Метод не изменяет исходный массив...

    Прогресс с моделью скрытой диффузии, часть 3 (машинное обучение)
    Выровняйте свои латентные данные: синтез видео высокого разрешения с моделями скрытой диффузии (arXiv) Автор: Андреас Блаттманн , Робин Ромбах , Хуан Линг , Тим Докхорн , Сын Ук Ким ,..

    Totaljs Flow: триггерные компоненты
    Total.js — это мощная и универсальная среда веб-приложений, которая предоставляет разработчикам ряд инструментов для оптимизации процесса разработки. Total.js Flow — самый популярный..

    Сквозное машинное обучение BigQuery
    Используйте Google Cloud BigQuery для участия в конкурсе Kaggle Я покажу вам, как прогнозировать выживших после катастрофы Титаника, используя только BigQuery и API Kaggle . С тех пор, как я..

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