Ваш алгоритм позволяет всему изображению, за исключением одного пикселя, быть "контуром". Я не уверен, что это именно то, что вы хотите; обычно контуром является граница между двумя разными областями. Проблема с вашим методом заключается в том, что вы можете получить огромные капли пикселей, у которых нет особенно очевидного порядка обхода. Если у вас есть контур толщиной в один пиксель, то порядок обхода гораздо более очевиден: по часовой стрелке или против часовой стрелки.
Рассмотрим следующее изображение.
........
..%%%%..
.%%%%...
...%%%%.
....%...
........
Здесь я пометил все «темное» (возможно, <50) как <code>% и все светлое как .
. Теперь вы можете выбрать любой пиксель, который находится на границе между двумя областями (я выберу темную сторону; вы также можете нарисовать контур на светлой стороне или, немного потрудившись, непосредственно между светлой и темной сторонами. ) * +1010 *
........
..%%%%..
.*%%%...
...%%%%.
....%...
........
Теперь вы пытаетесь путешествовать по внешнему краю темной области, по одному пикселю за раз. Сначала вы смотрите в направлении чего-то яркого (например, прямо влево). Затем вы вращаетесь вокруг - скажем, против часовой стрелки - пока не достигнете темного пикселя.
........
..%%%%..
1*5%%...
234%%%%.
....%...
........
Как только вы попали в позицию 5
, вы видите, что темно. Таким образом, вы помечаете его как часть контура, а затем пытаетесь найти следующий фрагмент на контуре, проводя вокруг, начиная с пикселя, с которого вы только что пришли
........
..%%%%..
.0*%%...
.123%%%.
....%...
........
Здесь 0
- это то, откуда вы пришли - и вы туда не вернетесь - и затем вы пробуете пиксели 1
и 2
(оба света, что не очень хорошо), пока вы не нажмете на пиксель 3
, что темно.
Таким образом, вы можете обходить контурный пиксель за пикселем - и идентифицировать контур, и получать порядок пикселей - до тех пор, пока вы не столкнетесь с тем же пикселем, с которого начинали , и не покинет это так, что вы попали в тот же пиксель, что и в первый раз, когда вы его оставили Тогда контур замыкается. В нашем примере, когда мы создаем 8-соединенный контур (т.е. мы смотрим на 8 соседей, а не 4), мы получим следующее (где @
обозначает точку контура).
........
..@@@@..
.@@%@...
...@%@@.
....@...
........
(У вас должен быть этот критерий «два в ряд» или если у вас темная область шириной в один пиксель, вы пройдете по ней вверх, но затем не сможете вернуться по ней.)
На данный момент вы покрыли одну всю границу. Но могут быть и другие. Продолжайте искать темные пиксели рядом со светлыми, пока вы не нарисуете контур поверх всех из них. Теперь вы преобразовали свое двухуровневое изображение (темные и яркие пиксели) в набор контуров.
Если контуры заканчиваются слишком шумно, сначала подумайте о размытии изображения. Это сгладит контуры. (В качестве альтернативы вы можете сначала найти контуры, а затем усреднить координаты с помощью движущегося окна.)