Как получить координаты белых точек на черном фоне
Немного предыстории:
Я строю арт-инсталляцию AR, и мне нужно отследить человека, который двигается по комнате.
Для этого я построил головной убор, который имеет несколько инфракрасных источников света (с рассеивателями) и камеру (веб-камера USB) с оптическим фильтром для удаления большинства / всего видимого света с изображения, а также несколько настроек к изображению, которое в основном оставляет меня с белыми точками на черном фоне.
Настроить веб-камеру таким образом, чтобы охватить границы комнаты, было довольно легко, но я не уверен, что нужно делать, а затем обрабатывать черно-белое изображение, чтобы получить координаты x,y каждой точки.
Пример вывода изображения: (Это макет, так как в этот момент у меня его нет, а также имейте в виду, что данные будут получены из видео)
Инструменты, которые я использую
- NodeJS для обработки
- Веб-камера Logitech для захвата изображения
- Google Cardboard для визуальных эффектов
- Инфракрасные светодиоды в шариках из пенопласта для приятного рассеянного света
Есть идеи?
3 ответа
Я могу придумать три способа сделать это с ImageMagick, который имеет node
bindings и устанавливается в большинстве дистрибутивов Linux и доступен для OSX и Windows.
Во-первых, просто введите в командной строке:
identify -precision 5 -define identify:locate=maximum -define identify:limit=3 image.png
Channel maximum locations:
Gray: 65535 (1) 146,164 147,164 148,164
и это показывает, что три самых ярких пикселя имеют ширину 146 пикселей от верхнего левого угла и 164 пикселя от верхнего левого угла, а два рядом с ним - справа.
В качестве альтернативы, если вас интересует область и / или центр тяжести точки, вы можете выполнить анализ связанных компонентов с помощью ImageMagick, который выглядит следующим образом:
convert image.png \
-colorspace gray -threshold 10% \
-define connected-components:verbose=true \
-connected-components 8 output.png
Objects (id: bounding-box centroid area mean-color):
0: 818x502+0+0 408.6,250.5 410539 srgb(0,0,0)
1: 11x11+143+164 148.0,169.0 97 srgb(255,255,255)
Это показывает вам (в последней строке вывода), что белый шарик имеет размер 11 x 11 пикселей и расположен на 143 пикселях поперек изображения от левого края и на 164 пикселя вниз от верха. Его центр тяжести - 148 169, площадь - 97 пикселей, цвет белый.
Первый найденный объект (от второй до последней строки вывода) - это все изображение, и вы можете не учитывать его, так как его цвет черный, т. Е. Rgb(0,0,0).
Я тоже могу немного объяснить параметры... Я преобразую в оттенки серого, потому что Coonected Component Analysis традиционно ищет белые объекты на черном фоне в черно-белом изображении. Затем я порог, чтобы получить чистый белый и чистый черный - вам может понадобиться медианный фильтр здесь в вашей реальной системе, чтобы избавиться от шума -median 3
, например. verbose=true
означает, что команда должна напечатать список всех больших двоичных объектов и 8
означает, что пиксели, которые соединены с 8 элементами, являются частями одного и того же большого двоичного объекта, то есть пиксель, касающийся другого в его углу NE, SE, SW или NW, считается частью того же самого большого двоичного объекта - если установить его на 4
пиксели должны быть непосредственно рядом или выше / ниже друг друга, чтобы считаться соседями.
Если вы хотите " вставить " область, которую он нашел, вы можете сделать это следующим образом:
convert image.png -stroke red -fill none -strokewidth 2 -draw "rectangle 143,164 154,175" output.png
Третий метод медленнее, и он включает в себя преобразование изображения в текст, а затем поиск слова "белый". Так. давайте начнем с простого и просто преобразуем изображение в текст следующим образом:
convert image.png -threshold 50% txt:
# ImageMagick pixel enumeration: 818,502,255,srgb
0,0: (0,0,0) #000000 black
1,0: (0,0,0) #000000 black
2,0: (0,0,0) #000000 black
3,0: (0,0,0) #000000 black
...
... 410,000 lines later
...
813,501: (0,0,0) #000000 black
814,501: (0,0,0) #000000 black
815,501: (0,0,0) #000000 black
816,501: (0,0,0) #000000 black
817,501: (0,0,0) #000000 black
Теперь давайте уточним это и посмотрим только на белые пиксели (в Windows вы бы использовали FINDSTR
скорее, чем grep
):
convert image.png -threshold 50% txt: | grep white
146,164: (255,255,255) #FFFFFF white
147,164: (255,255,255) #FFFFFF white
148,164: (255,255,255) #FFFFFF white
149,164: (255,255,255) #FFFFFF white
150,164: (255,255,255) #FFFFFF white
145,165: (255,255,255) #FFFFFF white
146,165: (255,255,255) #FFFFFF white
147,165: (255,255,255) #FFFFFF white
148,165: (255,255,255) #FFFFFF white
149,165: (255,255,255) #FFFFFF white
150,165: (255,255,255) #FFFFFF white
151,165: (255,255,255) #FFFFFF white
144,166: (255,255,255) #FFFFFF white
145,166: (255,255,255) #FFFFFF white
146,166: (255,255,255) #FFFFFF white
147,166: (255,255,255) #FFFFFF white
148,166: (255,255,255) #FFFFFF white
149,166: (255,255,255) #FFFFFF white
150,166: (255,255,255) #FFFFFF white
151,166: (255,255,255) #FFFFFF white
152,166: (255,255,255) #FFFFFF white
143,167: (255,255,255) #FFFFFF white
144,167: (255,255,255) #FFFFFF white
145,167: (255,255,255) #FFFFFF white
146,167: (255,255,255) #FFFFFF white
147,167: (255,255,255) #FFFFFF white
148,167: (255,255,255) #FFFFFF white
149,167: (255,255,255) #FFFFFF white
150,167: (255,255,255) #FFFFFF white
151,167: (255,255,255) #FFFFFF white
152,167: (255,255,255) #FFFFFF white
153,167: (255,255,255) #FFFFFF white
143,168: (255,255,255) #FFFFFF white
144,168: (255,255,255) #FFFFFF white
145,168: (255,255,255) #FFFFFF white
146,168: (255,255,255) #FFFFFF white
147,168: (255,255,255) #FFFFFF white
148,168: (255,255,255) #FFFFFF white
149,168: (255,255,255) #FFFFFF white
150,168: (255,255,255) #FFFFFF white
151,168: (255,255,255) #FFFFFF white
152,168: (255,255,255) #FFFFFF white
153,168: (255,255,255) #FFFFFF white
143,169: (255,255,255) #FFFFFF white
144,169: (255,255,255) #FFFFFF white
145,169: (255,255,255) #FFFFFF white
146,169: (255,255,255) #FFFFFF white
147,169: (255,255,255) #FFFFFF white
148,169: (255,255,255) #FFFFFF white
149,169: (255,255,255) #FFFFFF white
150,169: (255,255,255) #FFFFFF white
151,169: (255,255,255) #FFFFFF white
152,169: (255,255,255) #FFFFFF white
153,169: (255,255,255) #FFFFFF white
143,170: (255,255,255) #FFFFFF white
144,170: (255,255,255) #FFFFFF white
145,170: (255,255,255) #FFFFFF white
146,170: (255,255,255) #FFFFFF white
147,170: (255,255,255) #FFFFFF white
148,170: (255,255,255) #FFFFFF white
149,170: (255,255,255) #FFFFFF white
150,170: (255,255,255) #FFFFFF white
151,170: (255,255,255) #FFFFFF white
152,170: (255,255,255) #FFFFFF white
153,170: (255,255,255) #FFFFFF white
143,171: (255,255,255) #FFFFFF white
144,171: (255,255,255) #FFFFFF white
145,171: (255,255,255) #FFFFFF white
146,171: (255,255,255) #FFFFFF white
147,171: (255,255,255) #FFFFFF white
148,171: (255,255,255) #FFFFFF white
149,171: (255,255,255) #FFFFFF white
150,171: (255,255,255) #FFFFFF white
151,171: (255,255,255) #FFFFFF white
152,171: (255,255,255) #FFFFFF white
153,171: (255,255,255) #FFFFFF white
144,172: (255,255,255) #FFFFFF white
145,172: (255,255,255) #FFFFFF white
146,172: (255,255,255) #FFFFFF white
147,172: (255,255,255) #FFFFFF white
148,172: (255,255,255) #FFFFFF white
149,172: (255,255,255) #FFFFFF white
150,172: (255,255,255) #FFFFFF white
151,172: (255,255,255) #FFFFFF white
152,172: (255,255,255) #FFFFFF white
145,173: (255,255,255) #FFFFFF white
146,173: (255,255,255) #FFFFFF white
147,173: (255,255,255) #FFFFFF white
148,173: (255,255,255) #FFFFFF white
149,173: (255,255,255) #FFFFFF white
150,173: (255,255,255) #FFFFFF white
151,173: (255,255,255) #FFFFFF white
146,174: (255,255,255) #FFFFFF white
147,174: (255,255,255) #FFFFFF white
148,174: (255,255,255) #FFFFFF white
149,174: (255,255,255) #FFFFFF white
150,174: (255,255,255) #FFFFFF white
Что касается node
версия, я действительно не очень хорош в node
но я могу указать вам мой ответ здесь, который делает другой процесс ImageMagick через node
и надеемся, что вы сможете это адаптировать, если вы попробуете вышеизложенное в командной строке и обнаружите, что оно работает для вас достаточно хорошо, и вы хотите использовать ImageMagick.
Многие (большинство?) Библиотеки обработки изображений (например, OpenCV) имеют модуль извлечения подключенных компонентов. Учитывая бинарное изображение, как в вашем примере, вы получите список всех связанных областей изображения. Вы можете рассчитать их центр тяжести, чтобы получить центр ваших точек.
Одним из способов было бы использовать " преобразование Хафа". Простое преобразование в основном преобразует изображение в другую систему координат, где вы можете "легко" обнаружить круглые формы.
Я нашел nodejs-пример в другом вопросе. Я не уверен, что это сработало для них: hough transform - javascript - node.js
Вы также можете пройтись по каждому пикселю изображения и проверить, является ли он белым или нет, а если он белый, найти всех его белых соседей и удалить их. Вычислите их средние координаты xy и вуаля, у вас есть координаты вашей точки. Это, вероятно, хорошо работает, если у вас не слишком много шума.