Обычно обнаружение краев сводится к обнаружению областей изображения с высоким значением градиента.
В нашем случае мы можем грубо рассматривать градиент как производную функции изображения, поэтому величина градиента дает вам информацию о том, насколько ваше изображение изменяется локально (в отношении соседних пикселей / текселей).
Теперь, как вы говорите, ребро является признаком разрыва, так что теперь, когда мы определили градиент, стало ясно, что эта информация - все, что нам нужно. Как только мы находим градиент изображения, нужно просто применить к нему порог, чтобы получить двоичное значение ребро / не ребро.
Как вы нашли этот градиент действительно то, что вы спрашиваете, и я еще не ответил :)
Много способов! Здесь пара :)
Встроенные шейдерные функции
И hlsl, и glsl предлагают производные функции. В GLSL у вас есть dFdx и dFdy, которые дают вам соответственно информацию о градиенте в направлении x и y. Обычно эти функции оцениваются в блоке из фрагментов 2х2.
Если вас не интересует одно направление, хороший способ получить компактный результат, который показывает, насколько сильный градиент в области, - это ширина, которая не дает вам ничего, кроме суммы абсолютных значений dFdy и dFdy.
Скорее всего, вам будет интересен край изображения в целом, а не конкретного канала, поэтому вы можете захотеть преобразовать функцию изображения в яркость. Имея это в виду, когда дело доходит до обнаружения краев, ваш шейдер может включать что-то вроде:
float luminance = dot(yourFinalColour,vec3(0.2126, 0.7152, 0.0722));
float gradient = fwidth(luminance );
float isEdge = gradient > threshold;
С высоким порогом вы найдете более грубые края, и вы можете пропустить некоторые, наоборот, с низким порогом вы можете обнаружить ложные края. Вы должны экспериментировать, чтобы найти порог, который лучше соответствует вашим потребностям.
Стоит упомянуть причину, по которой эти функции работают, но сейчас у меня нет на это времени, я, скорее всего, обновлю этот ответ позже :)
Постобработка пространства экрана
Вы могли бы пойти дальше, чем это, теперь область обнаружения краев в обработке изображений огромна. Я мог бы привести вам десятки хороших способов обнаружения краев в соответствии с вашими потребностями, но давайте пока оставим это простым, если вам интересно, я могу привести вам больше вариантов!
Таким образом, идея будет аналогична приведенной выше, с той разницей, что вы можете посмотреть на более широкую окрестность и использовать набор весов для окружающих выборок, если хотите. Как правило, вы запускаете свертку над своим изображением с ядром, которое в результате дает вам хорошую информацию о градиенте.
Очень распространенным выбором является ядро Собеля
Что соответственно дает вам градиенты в направлениях х и у:
С г а дя е н т Мгп я т у де = ( г р а дя е н тИкс)2+ ( G r a dя е н тY)2-----------------------√
Тогда вы можете порог, как я упоминал выше.
Это ядро, как вы можете видеть, придает больший вес центральному пикселю, поэтому эффективно вычисляет градиент + немного сглаживания, что традиционно помогает (часто изображение размыто по Гауссу для устранения маленьких краев).
Вышеописанное работает довольно хорошо, но если вам не нравится сглаживание, вы можете использовать ядра Prewitt:
(Обратите внимание, я спешу, скоро напишу правильный форматированный текст вместо изображений!)
На самом деле существует гораздо больше ядер и методов для обнаружения краев в процессе обработки изображений, а не в графике в реальном времени, поэтому я исключил более запутанные (каламбурные) методы, так как, вероятно, вам будет хорошо с функциями dFdx / y ,