Этот вопрос является несколько агностическим языком, но мой предпочтительный инструмент, оказывается, массив numpy.
То, что я делаю, берет различие двух изображений через PIL:
img = ImageChops.difference(img1, img2)
И я хочу найти прямоугольные регионы, которые содержат изменения от одного изображения до другого. Конечно, существует встроенный .getbbox()
метод, но если существует два региона с изменениями, он возвратит поле от одного региона до другого, и если существуют изменения только на 1 пиксель в каждом углу, это возвратит целое изображение.
Например, рассмотрите следующее где o
ненулевой пиксель:
______________________
|o ooo |
| oooo ooo |
| o |
| o o |
| |
| oo o |
| o o ooo |
| oo ooooo |
| ooo |
| o |
|____________________|
Я хотел бы получить 4x4-кортежи, содержащие ограничительные рамки для каждого ненулевого региона. Для пограничного случая
oooo
o
o o
структура, я ужасно не волнуюсь, как это обработало - или получение обоих разделов отдельно или вместе, потому что границы инвертированной-L формы полностью перекроют границы единственного пикселя.
Я никогда не делал ничего, что это усовершенствовало с обработкой изображений, таким образом, я хотел получить некоторый вход, прежде чем я действительно запишу что-либо (и если там существуют ранее методы в модулях, я уже использую, я приветствую их!).
Моя версия psuedocode-выхода проходит примерно так:
for line in image:
started = False
for pixel in line:
if pixel and not started:
started = True
save start coords
elif started and not pixel:
started = False
save end coords (x - 1 of course)
Это должно дать мне список координат, но затем я должен определить, непрерывны ли регионы. Я мог сделать это с поиском типа графика? (Мы сделали много DFS и BFS в Алгоритмах в прошлом семестре), Конечно, я предполагаю, что мог сделать это вместо этого/в сочетании с мои предыдущие циклы?
Я не буду делать этого на "больших" изображениях - их вытягивают от веб-камеры и лучшей, которую я в настоящее время имею, делает 640x480. Самое большее я сделал бы 720 пунктов или 1 080 пунктов, но это достаточно далеко в будущее, что это не реальное беспокойство.
Так мой вопрос (вопросы): я направляюсь на правильном пути или являюсь мной путь прочь? И более важный, там какие-либо встроенные функции, которые препятствуют тому, чтобы я изобрел велосипед? И наконец, там какие-либо хорошие ресурсы, на которые я должен посмотреть (учебные руководства, бумаги, и т.д.), который поможет здесь?
Спасибо!
Я считаю, что модуль ndimage от scipy имеет все, что вам нужно. ..
Вот быстрый пример
import numpy as np
import scipy as sp
import scipy.ndimage.morphology
# The array you gave above
data = np.array(
[
[1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 0, 0, 0, 0],
[0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 0, 0, 0, 1, 1, 1, 0, 0, 0, 0],
[0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
[0, 0, 0, 0, 0, 0, 1, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
[0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
[0, 0, 0, 0, 0, 1, 1, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0],
[0, 0, 0, 0, 1, 0, 0, 1, 0, 0, 0, 0, 0, 1, 1, 1, 0, 0, 0, 0],
[0, 0, 0, 0, 0, 1, 1, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 0, 0, 0],
[0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 0, 0, 0, 0],
[0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0],
])
# Fill holes to make sure we get nice clusters
filled = sp.ndimage.morphology.binary_fill_holes(data)
# Now seperate each group of contigous ones into a distinct value
# This will be an array of values from 1 - num_objects, with zeros
# outside of any contigous object
objects, num_objects = sp.ndimage.label(filled)
# Now return a list of slices around each object
# (This is effectively the tuple that you wanted)
object_slices = sp.ndimage.find_objects(objects)
# Just to illustrate using the object_slices
for obj_slice in object_slices:
print data[obj_slice]
Это выводит:
[[1]]
[[1 1 1]
[1 1 1]]
[[1 1 1 1]
[1 0 0 0]
[1 0 0 1]]
[[1]]
[[0 1 1 0]
[1 0 0 1]
[0 1 1 0]]
[[0 0 1 0 0]
[0 1 1 1 0]
[1 1 1 1 1]
[0 1 1 1 0]
[0 0 1 0 0]]
Обратите внимание, что "object_slices" - это в основном то, что вы изначально просили, если вам нужны фактические признаки.
Редактирование: Просто хотел отметить, что несмотря на то, что кажется, что он правильно обрабатывает крайний случай
[[1 1 1 1]
[1 0 0 0]
[1 0 0 1]]
, на самом деле это не так (таким образом, лишняя одиночка [[1]]). Вы можете увидеть это, если распечатаете массив "objects" и посмотрите на объекты 3 и 4.
[[1 0 0 0 0 0 0 0 0 0 0 0 0 2 2 2 0 0 0 0]
[0 0 0 0 0 0 3 3 3 3 0 0 0 2 2 2 0 0 0 0]
[0 0 0 0 0 0 3 0 0 0 0 0 0 0 0 0 0 0 0 0]
[0 0 0 0 0 0 3 0 0 4 0 0 0 0 0 0 0 0 0 0]
[0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0]
[0 0 0 0 0 5 5 0 0 0 0 0 0 0 6 0 0 0 0 0]
[0 0 0 0 5 5 5 5 0 0 0 0 0 6 6 6 0 0 0 0]
[0 0 0 0 0 5 5 0 0 0 0 0 6 6 6 6 6 0 0 0]
[0 0 0 0 0 0 0 0 0 0 0 0 0 6 6 6 0 0 0 0]
[0 0 0 0 0 0 0 0 0 0 0 0 0 0 6 0 0 0 0 0]]
Надеюсь, это поможет!
[1]
Вы можете искать связанные компоненты в изображении, а затем определить граничные поля этих компонентов.
Пакет кластеризации (, т.е. этот ) должен уметь выполнять большую часть работы (находить связанные пиксели). Тогда найти ограничивающую рамку для кластера тривиально.